• HDU3726


    Portal

    Description

    给出一个(n(nleq2 imes10^4))个点,(m(mleq6 imes10^4))条边的有点权无向图。进行若干次操作:

    • 删除第(i)条边。
    • 求与点(u)连通的所有点中,权值第(k)大的点的权值。
    • 将点(u)的权值改为(x)

    Solution

    将操作离线,并从终止状态开始反向操作:删边变为加边,将权值由(x)修改成(y)变为由(y)改为(x)
    用splay维护每一个连通块内的权值,加边时启发式合并两棵splay,修改时删除再加入。
    启发式合并:合并两个数据结构时,将小的中的每个节点加入大的中。因为合成的数据结构大小至少是小的的两倍,所以一个节点最多被合并(O(logn))次,总复杂度就是(O(nlogn))

    Code

    //Graph and Queries
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int const N=2e4+10;
    int n,m;
    struct edge{int u,v,able;} ed[N*3];
    int cntQ;
    struct _query{char opt; int x,y;} qu[N*23];
    int pre[N];
    int find(int x) {return pre[x]==x?x:pre[x]=find(pre[x]);}
    int fa[N],ch[N][2],val[N],siz[N];
    int wh(int p) {return p==ch[fa[p]][1];}
    void reset(int p) {fa[p]=ch[p][0]=ch[p][1]=0; siz[p]=1;}
    void update(int p) {siz[p]=siz[ch[p][0]]+1+siz[ch[p][1]];}
    void rotate(int p)
    {
        int q=fa[p],r=fa[q],w=wh(p);
        fa[p]=r; if(r) ch[r][wh(q)]=p;
        fa[ch[q][w]=ch[p][w^1]]=q;
        fa[ch[p][w^1]=q]=p;
        update(q),update(p);
    }
    void splay(int p) {for(int q;q=fa[p];rotate(p)) if(fa[q]) rotate(wh(p)^wh(q)?p:q);}
    int root(int p) {while(fa[p]) p=fa[p]; return p;}
    void ins(int rt,int x)
    {
        if(rt==x) return;
        int p=rt,q=0; reset(x);
        while(p) q=p,p=ch[q][val[q]<val[x]];
        fa[ch[q][val[q]<val[x]]=x]=q; splay(x);
    }
    int del(int p)
    {
        splay(p); int chCnt=(ch[p][0]>0)+(ch[p][1]>0);
        if(chCnt==1)
        {
            int q=ch[p][ch[p][1]>0];
            fa[q]=0; reset(p); return q;
        }
        int q=ch[p][0]; while(ch[q][1]) q=ch[q][1];
        splay(q); fa[ch[q][1]=ch[p][1]]=q,update(q);
        return q;
    }
    int rnk(int rt,int x)
    {
        x=siz[rt]-x+1; 
        int p=rt;
        while(p)
            if(x<=siz[ch[p][0]]) p=ch[p][0];
            else if(siz[ch[p][0]]+1==x) return val[p];
            else if(x>siz[ch[p][0]]+1) x-=siz[ch[p][0]]+1,p=ch[p][1];
        return 0;
    }
    int cntT,tmp[N];
    void list(int p)
    {
        if(p==0) return;
        list(ch[p][0]),tmp[++cntT]=p,list(ch[p][1]);
    }
    void merge(int rt1,int rt2)
    {
        if(rt1==rt2) return;
        if(siz[rt1]>siz[rt2]) swap(rt1,rt2);
        cntT=0,memset(tmp,0,sizeof tmp); list(rt1);
        for(int i=1;i<=cntT;i++) ins(root(rt2),tmp[i]);
    }
    void change(int p,int x)
    {
        int rt=root(p); if(siz[rt]==1) {val[p]=x; return;}
        int q=del(p); val[p]=x,ins(root(q),p);
    }
    void init()
    {
        n=m=0; memset(ed,0,sizeof ed);
        cntQ=0; memset(qu,0,sizeof qu);
        memset(fa,0,sizeof fa),memset(ch,0,sizeof ch);
        memset(val,0,sizeof val),memset(siz,0,sizeof siz);
    }
    int main()
    {
        for(int owo=1;true;owo++)
        {
    
        init();
        scanf("%d%d",&n,&m); if(n==0&&m==0) break;
        for(int i=1;i<=n;i++) scanf("%d",&val[i]),siz[i]=1;
        for(int i=1;i<=m;i++) scanf("%d%d",&ed[i].u,&ed[i].v),ed[i].able=true;
        for(int i=1;true;i++)
        {
            scanf("
    %c",&qu[i].opt);
            if(qu[i].opt=='E') break;
            scanf("%d",&qu[i].x);
            if(qu[i].opt=='D') ed[qu[i].x].able=false;
            else if(qu[i].opt=='Q') scanf("%d",&qu[i].y);
            else if(qu[i].opt=='C') qu[i].y=val[qu[i].x],scanf("%d",&val[qu[i].x]);
            cntQ=i;
        }
        for(int i=1;i<=n;i++) pre[i]=i;
        for(int i=1;i<=m;i++)
        {
            if(!ed[i].able) continue;
            int u=ed[i].u,v=ed[i].v;
            if(find(u)!=find(v)) pre[find(u)]=find(v);
        }
        for(int i=1;i<=n;i++) if(i!=find(i)) ins(root(find(i)),i);
        long long ans=0; int cnt0=0;
        for(int i=cntQ;i>=1;i--)
        {
            char opt=qu[i].opt; int x=qu[i].x,y=qu[i].y;
            if(opt=='D') merge(root(ed[x].u),root(ed[x].v));
            else if(opt=='Q') ans+=rnk(root(x),y),cnt0++;
            else if(opt=='C') change(x,y);
        }
        printf("Case %d: %.6lf
    ",owo,(double)ans/cnt0);
        
        }
        return 0;
    }
    

    P.S.

    原来启发式合并这么简单...我以前以为超级高大上的
    为什么HDU净是多组测试数据,还不告诉你有多少操作叫你自己读...

  • 相关阅读:
    文献阅读 | On the subspecific origin of the laboratory mouse
    文献阅读 | GenomicsDB: storing genome data as sparse columnar arrays.
    文献阅读 | The human Y chromosome: an evolutionary marker comes of age
    文献阅读 | HaploGrouper: A generalized approach to haplogroup classification
    文献阅读 | Systematic evaluation of error rates and causes in short samples in next-generation sequencing
    文献阅读 | The Wheat 660K SNP array demonstrates great potential for marker‐assisted selection in polyploid wheat
    使用HMM进行分类识别(以语音识别为例)
    文献阅读 | Fine definition of the pedigree haplotypes of closely related rice cultivars by means of genome-wide discovery of single-nucleotide polymorphisms
    GWAS学习笔记(一) | 质量控制(QC)
    python实现简单决策树(信息增益)——基于周志华的西瓜书数据
  • 原文地址:https://www.cnblogs.com/VisJiao/p/HDU3726.html
Copyright © 2020-2023  润新知