bzoj2733 / P3224 [HNOI2012]永无乡(并查集+线段树合并)

[HNOI2012]永无乡

每个联通块的点集用动态开点线段树维护

并查集维护图

合并时把线段树也合并就好了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cctype>
 5 #define re register 
 6 #define gc getchar
 7 using namespace std;
 8 void chread(char &x){
 9     char c=gc();
10     while(!isupper(c)) c=gc();
11     x=c;
12 }
13 void read(int &x){
14     char c=gc();x=0; bool f=1;
15     while(!isdigit(c)) f=(f&&c!='-'),c=gc();
16     while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=gc();
17     x=f?x:-x;
18 }
19 void swap(int &a,int &b){a^=b;b^=a;a^=b;}
20 #define N 100002
21 #define M 600002
22 struct edge{int u,v;bool del;}b[M];
23 struct node{
24     int sum,lc,rc;
25 }c[M<<2];
26 int n,m,t,u,val[N],fa[N],rt[N],ttp,id[N];
27 double ans;
28 
29 void update(int &o,int l,int r,int v,int k){//插入
30     if(!o) o=++u;
31     if(l==r) {c[o].sum+=k; return;}
32     int mid=l+((r-l)>>1);
33     if(v<=mid) update(c[o].lc,l,mid,v,k);
34     else update(c[o].rc,mid+1,r,v,k);
35     c[o].sum=c[c[o].lc].sum+c[c[o].rc].sum;
36 }
37 void merge(int &o,int pr){//合并
38     if(!o||!pr) {o+=pr;return;}
39     c[o].sum+=c[pr].sum;
40     merge(c[o].lc,c[pr].lc);
41     merge(c[o].rc,c[pr].rc);
42 }
43 int query(int o,int l,int r,int k){//询问
44     if(l==r) return l;
45     int mid=l+((r-l)>>1);
46     if(k<=c[c[o].lc].sum) return query(c[o].lc,l,mid,k);
47     else return query(c[o].rc,mid+1,r,k-c[c[o].lc].sum);
48 }
49 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
50 void uni(int x,int y){//并查集合并
51     int r1=find(x),r2=find(y);
52     if(r1!=r2){
53         merge(rt[r1],rt[r2]);
54         fa[r2]=r1;
55     }
56 }
57 int ask(int x,int k){
58     int ffa=find(x);
59     return k>c[rt[ffa]].sum ?-1:id[query(rt[ffa],1,n,k)];
60 }
61 int main(){
62     char opt; int q1,q2;
63     read(n); read(m);
64     for(re int i=1;i<=n;++i){
65         read(val[i]),id[val[i]]=i,fa[i]=i;
66         update(rt[i],1,n,val[i],1);
67     }
68     for(re int i=1;i<=m;++i) read(q1),read(q2),uni(q1,q2);
69     read(t);
70     for(re int i=1;i<=t;++i){
71         chread(opt); read(q1); read(q2); 
72         switch(opt){
73             case 'B':{uni(q1,q2); break;}
74             case 'Q':{printf("%d\n",ask(q1,q2));  break;}
75         }
76     }
77     return 0;
78 }
View Code

 

posted @ 2018-10-24 20:34  kafuuchino  阅读(142)  评论(0编辑  收藏  举报