bzoj2733[HNOI2012]永无乡

%%%lych_cys讲的线段树合并

蛮水的题,交上去一发MLE(made居然这年头还有128M的题,我瞎开了好多)一发AC

 1 #include <bits/stdc++.h> 
 2 #define N 200001
 3 #define mid (l+r>>1)
 4 using namespace std;
 5 int NODE,n,m,wei,root[N],p,q;char ch;
 6 int fa[N],tr[N*20],rs[N*20],ls[N*20],rk[N];
 7 int getfa(int x)
 8 {
 9     if(fa[x]==x) return x;
10     else return fa[x]=getfa(fa[x]);
11 }
12 int change(int ac,int l,int r,int x)
13 {
14     int now=++NODE;
15     if(l==r)
16     {
17         ++tr[now];
18         return now;
19     }
20     if(x<=mid) rs[now]=rs[ac],ls[now]=change(ls[ac],l,mid,x);
21     else ls[now]=ls[ac],rs[now]=change(rs[ac],mid+1,r,x);
22     tr[now]=tr[ls[now]]+tr[rs[now]];
23     return now;
24 }
25 void merge(int x,int y)
26 {
27     tr[y]+=tr[x];
28     if(!ls[y]) ls[y]=ls[x];
29     else
30         if(ls[x]) merge(ls[x],ls[y]);
31     if(!rs[y]) rs[y]=rs[x];
32     else
33         if(rs[x]) merge(rs[x],rs[y]);
34 } 
35 int que(int now,int l,int r,int x)
36 {
37     while(l<r)
38         if(tr[ls[now]]<x) x-=tr[ls[now]],l=mid+1,now=rs[now];
39         else r=mid,now=ls[now];
40     return tr[now]?rk[l]:-1;
41 }
42 int main()
43 {
44     scanf("%d%d",&n,&m);
45     for(int i=1;i<=n;i++)
46     {
47         scanf("%d",&wei);
48         rk[wei]=i;
49         root[i]=change(0,1,n,wei);
50         fa[i]=i;
51     }
52     for(int i=1;i<=m;i++)
53         scanf("%d%d",&p,&q),merge(root[getfa(p)],root[getfa(q)]),fa[getfa(p)]=getfa(q);
54     scanf("%d",&m);
55     for(int i=1;i<=m;i++)
56     {
57         for(ch=getchar();!isalpha(ch);ch=getchar());
58         scanf("%d%d",&p,&q);
59         if(ch=='B') merge(root[getfa(p)],root[getfa(q)]),fa[getfa(p)]=getfa(q);
60         if(ch=='Q') printf("%d\n",que(root[getfa(p)],1,n,q));
61     }
62     return 0;
63 }

 

posted @ 2017-07-10 14:13  汪立超  阅读(188)  评论(0编辑  收藏  举报