[BZOJ2733][HNOI2012]永无乡 线段树合并

Posted halfrot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ2733][HNOI2012]永无乡 线段树合并相关的知识,希望对你有一定的参考价值。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2733

我们对每一个连通块建一棵以排名为键值的权值线段树,询问就可以用二分的方法。

然后对于块与块间加边,我们用并查集维护连通性,每次合并两个块的时候,因为线段树结构相同,可以直接合并就行了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int inline readint(){
 6     int Num;char ch;
 7     while((ch=getchar())<0||ch>9);Num=ch-0;
 8     while((ch=getchar())>=0&&ch<=9) Num=Num*10+ch-0;
 9     return Num;
10 }
11 void outint(int x){
12     if(x>=10) outint(x/10);
13     putchar(x%10+0);
14 }
15 int N,M,Q;
16 int a[100010],re[100010];
17 int Rt[100010],lc[2000010],rc[2000010],cnt=0;
18 int sum[2000010];
19 int fa[100010];
20 int inline Getfa(int x){
21     return fa[x]==x?x:fa[x]=Getfa(fa[x]);
22 }
23 void Pushup(int &rt){
24     sum[rt]=sum[lc[rt]]+sum[rc[rt]];
25 }
26 void Insert(int &rt,int l,int r,int x){
27     if(!rt) rt=++cnt;
28     if(l==r){
29         sum[rt]=1;
30         return;
31     }
32     int mid=l+r>>1;
33     if(x<=mid) Insert(lc[rt],l,mid,x);
34     else Insert(rc[rt],mid+1,r,x);
35     Pushup(rt);
36 }
37 int Merge(int x,int y){
38     if(!x||!y) return x+y;
39     lc[x]=Merge(lc[x],lc[y]);
40     rc[x]=Merge(rc[x],rc[y]);
41     Pushup(x);
42     return x;
43 }
44 int Qry(int rt,int l,int r,int x){
45     if(l==r) return l;
46     int mid=l+r>>1;
47     if(sum[lc[rt]]>=x) return Qry(lc[rt],l,mid,x);
48     else return Qry(rc[rt],mid+1,r,x-sum[lc[rt]]);
49 }
50 int main(){
51     N=readint();
52     M=readint();
53     for(int i=1;i<=N;i++){
54         a[i]=readint();
55         Insert(Rt[i],1,N,a[i]);
56         re[a[i]]=i;
57     }
58     for(int i=1;i<=N;i++) fa[i]=i;
59     for(int i=1;i<=M;i++){
60         int A=readint(),
61             B=readint(),
62             fA=Getfa(A),
63             fB=Getfa(B);
64         fa[fB]=fA;
65         Rt[fA]=Merge(Rt[fA],Rt[fB]);
66     }
67     Q=readint();
68     for(int i=1;i<=Q;i++){
69         char opt[5];
70         scanf("%s",opt);
71         int x=readint(),
72             y=readint();
73         switch(opt[0]){
74             case Q:
75                 x=Getfa(x);
76                 if(sum[Rt[x]]<y){
77                     puts("-1");
78                     break;
79                 }
80                 outint(re[Qry(Rt[x],1,N,y)]);
81                 putchar(\n);
82                 break;
83             case B:
84                 x=Getfa(x);
85                 y=Getfa(y);
86                 if(x==y) break;
87                 fa[y]=x;
88                 Rt[x]=Merge(Rt[x],Rt[y]);
89                 break;
90         }
91     }
92     return 0;
93 }

 

以上是关于[BZOJ2733][HNOI2012]永无乡 线段树合并的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2733: [HNOI2012]永无乡 启发式合并

[BZOJ] 2733: [HNOI2012]永无乡 #线段树合并+并查集

Bzoj 2733: [HNOI2012]永无乡 数组Splay+启发式合并

bzoj 2733: [HNOI2012]永无乡

BZOJ2733: [HNOI2012]永无乡

[bzoj2733] [HNOI2012]永无乡