LA 5031 Graph and Queries(Treap)

  • Post author:
  • Post category:其他




思路大概就是把操作倒着做,先生成最终的图,每个连通块建一棵treap,删边变成添边,如果连接的两个连通块本来不连通,那么就把两个树合并。修改的操作转化成删除一个点再添加一个点。查询就直接查询就好了。操作比较多,感觉有些地方不太好想,看了看白书的代码,有些细节的地方才想明白。。。







代码:




#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=500000+100;
const int N=20000+100;
const int M=60000+100;
int ch[maxn][2],val[maxn],counts[maxn],size[maxn],r[maxn];
int root[maxn],S[maxn],tot,tot2;
void NewNode(int &rt,int v)
{
    if(tot2) rt=S[tot2--];
    else rt=++tot;
    ch[rt][0]=ch[rt][1]=0;
    size[rt]=counts[rt]=1;
    val[rt]=v;r[rt]=rand();
}
inline void PushUp(int rt)
{
    size[rt]=size[ch[rt][0]]+size[ch[rt][1]]+counts[rt];
}
void Rotate(int &x,int kind)
{
    int y=ch[x][kind^1];
    ch[x][kind^1]=ch[y][kind];
    ch[y][kind]=x;
    PushUp(x);PushUp(y);
    x=y;
}
void Insert(int &rt,int v)
{
    if(rt==0)
    {
        NewNode(rt,v);
        return ;
    }
    if(val[rt]==v)
        counts[rt]++;
    else
    {
        int kind=(v>val[rt]);
        Insert(ch[rt][kind],v);
        if(r[ch[rt][kind]]<r[rt])
            Rotate(rt,kind^1);
    }
    PushUp(rt);
}
void Remove(int &rt,int v)
{
    if(val[rt]==v)
    {
        if(counts[rt]>1)
            counts[rt]--;
        else if(!ch[rt][0]&&!ch[rt][1])
        {S[++tot2]=rt;rt=0;return;}
        else
        {
            int kind=r[ch[rt][0]]<r[ch[rt][1]];
            Rotate(rt,kind);
            Remove(rt,v);
        }
    }
    else Remove(ch[rt][v>val[rt]],v);
    PushUp(rt);
}
int select(int rt,int k)
{
    if(size[ch[rt][1]]>=k) return select(ch[rt][1],k);
    if(size[ch[rt][1]]+counts[rt]>=k) return val[rt];
    return select(ch[rt][0],k-(size[ch[rt][1]]+counts[rt]));
}
int pa[N],weight[N];
int Find(int x)
{
    return x==pa[x]?x:pa[x]=Find(pa[x]);
}
struct Command
{
    int type,x,v;
    Command(){}
    Command(int type,int x,int v):type(type),x(x),v(v){}
}commands[maxn];
struct Edge
{
    int u,v;
}edges[M];
bool removed[M];
void changes(int x,int v)
{
    int u=Find(x);
    Remove(root[u],weight[x]);
    Insert(root[u],v);
    weight[x]=v;
}
int query(int x,int k)
{
    if(k<=0) return 0;
    x=Find(x);
    if(size[root[x]]<k) return 0;
    return select(root[x],k);
}
void mergeto(int &x,int &y)
{
    if(x==0) return ;
    if(ch[x][0]) mergeto(ch[x][0],y);
    if(ch[x][1]) mergeto(ch[x][1],y);
    while(counts[x]>=1) {Insert(y,val[x]);counts[x]--;}
    S[++tot2]=x;
    x=0;
}
void add_edges(int u,int v)
{
    u=Find(u),v=Find(v);
    if(u==v) return ;
    if(size[root[u]]>size[root[v]])
        mergeto(root[v],root[u]),pa[v]=u;
    else
        mergeto(root[u],root[v]),pa[u]=v;
}
void Init()
{
    memset(root,0,sizeof(root));
    ch[0][1]=ch[0][0]=0;
    size[0]=counts[0]=0;
    val[0]=0;r[0]=(1LL<<31)-1;
    tot=tot2=0;
}
double solve(int n,int m)
{
    Init();
    memset(removed,0,sizeof(removed));
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&weight[i]);
        pa[i]=i;
    }
    for(int i=1;i<=m;++i)
        scanf("%d%d",&edges[i].u,&edges[i].v);
    char str[5];
    int type,x,v,q_cnt=0,q=0;
    ll sum=0;
    while(true)
    {
        scanf("%s",str);
        if(str[0]=='E') break;
        scanf("%d",&x);
        if(str[0]=='D')
            removed[x]=true,type=0;
        else
        {
            scanf("%d",&v);
            if(str[0]=='C')
            {
                swap(weight[x],v);
                type=2;
            }
            else type=1;
        }
        commands[q++]=Command(type,x,v);
    }
    for(int i=1;i<=n;++i)
        NewNode(root[i],weight[i]);
    for(int i=1;i<=m;++i)
        if(!removed[i]) add_edges(edges[i].u,edges[i].v);
    for(int i=q-1;i>=0;--i)
    {
        type=commands[i].type;x=commands[i].x;v=commands[i].v;
        if(type==0) add_edges(edges[x].u,edges[x].v);
        else if(type==1)
        {
            sum+=query(x,v);
            q_cnt++;
        }
        else changes(x,v);
    }
    return sum/(double)q_cnt;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,m,tcase=0;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        tcase++;
        double ans=solve(n,m);
        printf("Case %d: %.6lf\n",tcase,ans);
    }
    return 0;
}



版权声明:本文为qian99原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。