hdu 3726 Graph and Queries

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#define L ch[rt][0]
#define R ch[rt][1]
const int N = 411111;
const int maxn = 111111;
int ch[maxn][2], aux[maxn], num[maxn], size[maxn], cnt[maxn];
int Node[511111];
int weight[N];
int val[maxn],tot,tot1;
bool v[maxn];
inline void NewNode(int &rt)
{
    if(tot1)
        rt=Node[--tot1];
    else
        rt=++tot;
}
struct Treap
{
    int rt;
    inline void init()
    {
        rt=0;
        size[rt] = 0;
        ch[rt][0] = ch[rt][1] = 0;
        aux[rt] = 0;
        v[rt]=false;
    }
    inline void pushup(int rt)
    {
        size[rt] = cnt[rt] + size[L]+size[R];
    }
    inline void rotate(int &rt,int f)
    {
        int t=ch[rt][!f];
        ch[rt][!f]=ch[t][f];
        ch[t][f]=rt;
        pushup(rt),pushup(t);
        rt=t;
    }
    void insert(int &rt,int key)
    {
        if(!rt)
        {
            NewNode(rt);
            val[rt]=key;
            L=R=0;
            size[rt]=cnt[rt]=1;
            aux[rt]=(rand()<<14)+rand();
            return;
        }

        if(key<=val[rt])
        {
            insert(L,key);
            if(aux[L]<aux[rt])
                rotate(rt,1);
        }
        else if(key>val[rt])
        {
            insert(R,key);
            if(aux[R]<aux[rt])
                rotate(rt,0);
        }
        pushup(rt);
    }
    void treap_delete(int &rt)
    {
        if(!L||!R)
        {
            rt=L?L:R;
        }
        else
        {
            if(aux[L]<aux[R])
            {
                rotate(rt,1);
                treap_delete(R);
            }
            else
            {
                rotate(rt,0);
                treap_delete(L);
            }

        }
    }
    void del(int &rt,int key)
    {
        if(!rt) return;
        if(key==val[rt])
        {
            cnt[rt]--;
            size[rt]--;
            if(cnt[rt]==0)
            {
                Node[tot1++]=rt;
                treap_delete(rt);
            }
        }
        else
        {
            if(key<val[rt])
                del(L,key);
            else
                del(R,key);
            size[rt]--;
        }
    }
    int find(int rt,int key)
    {
        if(!rt) return -1;
        else if(key<val[rt]) return find(L,key);
        else if(key>val[rt]) return find(R,key);
        else return rt;
    }
    void succ(int rt,int key,int &ans)
    {
        if(!rt) return;
        if(val[rt]>=key)
        {
            ans=val[rt];
            succ(L,key,ans);
        }
        else
            succ(R,key,ans);
    }
    void pre(int rt,int key,int &ans)
    {
        if(!rt) return;
        if(val[rt]<=key)
        {
            ans=val[rt];
            pre(R,key,ans);
        }
        else
            pre(L,key,ans);
    }
    int getmin(int rt)
    {
        while(L)
            rt=L;
        return val[rt];
    }
    int getmax(int rt)
    {
        while(R)
            rt=R;
        return val[rt];
    }
    int find_kth(int rt,int k)
    {
        if(!rt) return 0;
        if(k>size[R]+cnt[rt])
            return find_kth(L,k-cnt[rt]-size[R]);
        else if(k<=size[R])
            return find_kth(R,k);
        return val[rt];
    }
} tree[21111];
int a[N],b[N],f[N];
int type[N],x[N],y[N];
char op[14];
int n,m,q;
bool ok[N];
inline int find(int n)
{
    return f[n]!=n?f[n]=find(f[n]):n;
}
inline void dfs(int rt,int u)
{
    if(L)
        dfs(L,u);
    if(R)
        dfs(R,u);
    tree[u].insert(tree[u].rt,val[rt]);
}
inline void merge(int u,int v)
{
    f[v]=u;
    dfs(tree[v].rt,u);
}
int main()
{
    int i;
    int cas=0;
    while(~scanf("%d%d",&n,&m)&&(n|m))
    {
        tot=tot1=0;
        for(i=1;i<=n;++i) f[i]=i;
        for(i=1;i<=n;++i) scanf("%d",weight+i);
        for(i=1;i<=m;++i) scanf("%d%d",a+i,b+i),ok[i]=true;
        q=0;
        for(i=1;;++i)
        {
            scanf("%s",op);
            if(op[0]=='E') break;
            if(op[0]=='D')
            {
                type[i]=1;
                scanf("%d",x+i);
                ok[x[i]]=false;
            }
            else if(op[0]=='Q')
            {
                type[i]=2;
                scanf("%d%d",x+i,y+i);
            }
            else
            {
                type[i]=3;
                int tmp;
                scanf("%d%d",x+i,y+i);
                tmp=weight[x[i]];
                weight[x[i]]=y[i];
                y[i]=tmp;
            }
        }
        q=i-1;
        int u,v;
        for(i=1;i<=m;++i)
        {
            if(ok[i])
            {

                u=find(a[i]);
                v=find(b[i]);
                if(u!=v)
                {
                    f[u]=v;
                }
            }
        }
        int r1,r2;
        double ans=0;
        int Ccnt=0;
        for(i=1;i<=n;++i) tree[i].init(),find(f[i]);
        for(i=1;i<=n;++i)
        {
            u=find(f[i]);
            tree[u].insert(tree[u].rt,weight[i]);
        }
        for(i=q;i>=1;--i)
        {

            if(type[i]==1)
            {
                u=a[x[i]];
                v=b[x[i]];
                u=find(u);
                v=find(v);
                if(u!=v)
                {
                    r1=tree[u].rt;
                    r2=tree[v].rt;
                    if(size[r1]>=size[r2])
                        merge(u,v);
                    else
                        merge(v,u);
                }
            }

            if(type[i]==2)
            {
                u=find(x[i]);
                Ccnt++;
                double tmp=0;
                if(y[i]<=0||y[i]>size[tree[u].rt])
                    tmp=0;
                else
                    tmp=tree[u].find_kth(tree[u].rt,y[i]);
                ans+=tmp;
            }

            if(type[i]==3)
            {
                u=find(x[i]);
                tree[u].del(tree[u].rt,weight[x[i]]);
                weight[x[i]]=y[i];
                tree[u].insert(tree[u].rt,weight[x[i]]);
            }
        }
        if(Ccnt)
            ans=ans/Ccnt;
        printf("Case %d: %.6f\n",++cas,ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值