zoukankan      html  css  js  c++  java
  • bzoj 2733: [HNOI2012]永无乡 离线+主席树

    2733: [HNOI2012]永无乡

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1167  Solved: 607
    [Submit][Status]

    Description

    永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。 
     

    Input

    输入文件第一行是用空格隔开的两个正整数 n 和 m,分别 表示岛的个数以及一开始存在的桥数。接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 ai 和 bi,表示一开始就存 在一座连接岛 ai 和岛 bi 的桥。后面剩下的部分描述操作,该部分的第一行是一个正整数 q, 表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 Q 或B 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。 对于 20%的数据 n≤1000,q≤1000 
     
    对于 100%的数据 n≤100000,m≤n,q≤300000 
     

    Output

    对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表 示所询问岛屿的编号。如果该岛屿不存在,则输出-1。 
     

    Sample Input

    5 1
    4 3 2 5 1
    1 2
    7
    Q 3 2
    Q 2 1
    B 2 3
    B 1 5
    Q 2 1
    Q 2 4
    Q 2 3

    Sample Output

    -1
    2
    5
    1
    2
     
      orz,这道题居然有nlogn的算法,现将所有合并操作模拟一遍,每次加一个虚拟父节点,建出一棵树,然后求出这棵树叶子节点的dfs序,每次询问就等于询问dfs序下的区间第k大,主席书。。。。
      这种方法的确很恶心。。。
      另:看清楚数据范围啊!
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXN 210000
    #define MAXV 210000
    #define MAXE 420000
    #define MAXT 4010000
    #define MAXQ 310000
    int n,m;
    int vv[MAXN];
    int avv[MAXN];
    struct Edge
    {
            int np,val;
            Edge *next;
    }E[MAXE],*V[MAXV];
    int tope=-1;
    void addedge(int x,int y)
    {
            //cout<<"Add: "<<x<<" "<<y<<endl;
            E[++tope].np=y;
            E[tope].next=V[x];
            V[x]=&E[tope];
    }
    int uf[MAXN];
    int topn;
    int get_fa(int now)
    {
            return (uf[now]==now)?now:(uf[now]=get_fa(uf[now]));
    }
    int comb(int x,int y)
    {
            x=get_fa(x);
            y=get_fa(y);
            if (x==y)return false;
            topn++;
    //        addedge(x,topn);
            addedge(topn,x);
    //        addedge(y,topn);
            addedge(topn,y);
            uf[x]=topn;
            uf[y]=topn;
            uf[topn]=topn;
            return topn;
    }
    struct qur_t
    {
            int x,y;
            int val;
            char opt;
    }qur[MAXQ];
    int q[MAXN],topq;
    int fa[MAXN];
    int siz[MAXN];
    int pos[MAXN];
    int sub_s[MAXN],sub_t[MAXN];
    void bfs(int rt)
    {
            int head=-1,tail=0;
            Edge *ne;
            int now;
            int i;
            q[0]=rt;
            while (head<tail)
            {
                    now=q[++head];
                    for (ne=V[now];ne;ne=ne->next)
                    {
                            fa[ne->np]=now;
                            q[++tail]=ne->np;
                    }
            }
            topq=tail;
            for (i=topq;i>=0;i--)
            {
                    siz[q[i]]=V[q[i]]==0;
                    for (ne=V[q[i]];ne;ne=ne->next)
                    {
                            siz[q[i]]+=siz[ne->np];
                    }
            }
            pos[rt]=1;
            int x;
            for (i=0;i<=topq;i++)
            {
                    now=q[i];
                    x=pos[now];
                    sub_s[now]=x;
                    for(ne=V[now];ne;ne=ne->next)
                    {
                            pos[ne->np]=x;
                            x+=siz[ne->np];
                    }
                    x+=V[now]==0;
                    sub_t[now]=x-1;
                    if (V[now])pos[now]=-1;
            }
    }
    
    struct sgt_node
    {
            int lch,rch,sum;
    }sgt[MAXT];
    int root[MAXN];
    int topt=0;
    void Add_val(int base,int &now,int l,int r,int pos,int v)
    {
            now=++topt;
            sgt[now]=sgt[base];
            if (l==r)
            {
                    sgt[now].sum+=v;
                    return ;
            }
            if (pos<=((l+r)>>1))
            {
                    Add_val(sgt[base].lch,sgt[now].lch,l,(l+r)>>1,pos,v);
            }else
            {
                    Add_val(sgt[base].rch,sgt[now].rch,((l+r)>>1)+1,r,pos,v);
            }
            sgt[now].sum=sgt[sgt[now].lch].sum+sgt[sgt[now].rch].sum;
    }
    int Qry_kth(int lt,int rt,int rk)
    {
            lt=root[lt-1];
            rt=root[rt];
            if (sgt[rt].sum-sgt[lt].sum<rk)return -1;
            int l,r,mid;
            l=1,r=n;
            while (l!=r)
            {
                    mid=(l+r)>>1;
                    if (sgt[sgt[rt].lch].sum-sgt[sgt[lt].lch].sum<rk)
                    {
                            rk-=sgt[sgt[rt].lch].sum-sgt[sgt[lt].lch].sum;
                            rt=sgt[rt].rch;
                            lt=sgt[lt].rch;
                            l=mid+1;
                    }else
                    {
                            rt=sgt[rt].lch;
                            lt=sgt[lt].lch;
                            r=mid;
                    }
            }
            return avv[l];
    }
    
    
    int v2[MAXN];
    int bb[MAXN][2];
    int main()
    {
            freopen("input.txt","r",stdin);
    //        freopen("output.txt","w",stdout);
            int i,j,k,x,y,z;
            scanf("%d%d",&n,&m);
            for (i=0;i<=n;i++)uf[i]=i;
            for (i=0;i<n;i++)
            {
                    scanf("%d",&vv[i+1]);
                    avv[vv[i+1]]=i+1;
            }
            topn=n;
            for (i=0;i<m;i++)
            {
                    scanf("%d%d",&x,&y);
                    bb[i][0]=x;
                    bb[i][1]=y;
                    comb(x,y);
            }
            int q;
            scanf("%d
    ",&q);
            char opt;
            for (i=0;i<q;i++)
            {
                    scanf("%c%d%d
    ",&qur[i].opt,&qur[i].x,&qur[i].y);
                    if (qur[i].opt=='B')
                            qur[i].val=comb(qur[i].x,qur[i].y);
            }
            topn++;
            uf[topn]=topn;
            for (i=1;i<=n;i++)
            {
                    if (get_fa(i)!=topn)
                    {
                            addedge(topn,get_fa(i));
                            uf[get_fa(i)]=topn;
                    }
            }
            bfs(topn);
            for (i=1;i<=n;i++)
            {
                    v2[pos[i]]=vv[i];
            }
            for (i=1;i<=n;i++)
            {
                    Add_val(root[i-1],root[i],1,n,v2[i],1);
            }
            topn=n;
            for (i=0;i<=n;i++)
                    uf[i]=i;
            //cout<<"---------------------------------------------"<<endl;
            for (i=0;i<m;i++)
            {
                    comb(bb[i][0],bb[i][1]);
            }
            for (i=0;i<q;i++)
            {
                    if (qur[i].opt=='Q')
                    {
                            printf("%d
    ",Qry_kth(sub_s[get_fa(qur[i].x)],sub_t[get_fa(qur[i].x)],qur[i].y));
                    }else
                    {
                            comb(qur[i].x,qur[i].y);
                    }
            }
            return 0;
    }
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    SQL学习
    FOR XML PATH
    IOS学习网址
    weak nonatomic strong等介绍(ios)
    UVALive3045 POJ2000 ZOJ2345 Gold Coins
    UVA713 UVALive5539 POJ1504 ZOJ2001 Adding Reversed Numbers
    UVA713 UVALive5539 POJ1504 ZOJ2001 Adding Reversed Numbers
    UVA439 POJ2243 HDU1372 ZOJ1091 Knight Moves【BFS】
    UVA439 POJ2243 HDU1372 ZOJ1091 Knight Moves【BFS】
    UVA10905 Children's Game
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4039639.html
Copyright © 2011-2022 走看看