2733: [HNOI2012]永无乡 线段树合并

题目:

  https://www.lydsy.com/JudgeOnline/problem.php?id=2733

题解:

  建n棵动态开点的权值线段树,然后边用并查集维护连通性,边合并线段树维护第k重要。

  其实实现还是很简单的。。

代码:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn=300010;
 6 int fa[maxn],root[maxn],n,m,g[maxn],f[maxn],id;
 7 char ch[3];
 8 
 9 struct Tr{
10     int lt,rt,num;
11     int ch[2];
12 }tree[maxn<<3];
13 
14 void update(int now){
15     tree[now].num=tree[tree[now].ch[0]].num+tree[tree[now].ch[1]].num;
16 }
17 
18 int merge(int now,int last){
19     if(!now) return last;
20     else if(!last) return now;
21     if(tree[now].num<tree[last].num) swap(now,last);
22     tree[now].ch[0]=merge(tree[now].ch[0],tree[last].ch[0]);
23     tree[now].ch[1]=merge(tree[now].ch[1],tree[last].ch[1]);
24     update(now);return now;
25 }
26 
27 int ffa(int x){
28     return fa[x]==x?x:fa[x]=ffa(fa[x]);
29 }
30 
31 void connect(int u,int v){
32     int fu=ffa(u),fv=ffa(v);
33     if(fu!=fv) root[fu]=merge(root[fu],root[fv]),fa[fv]=fu;
34 }
35 
36 void build(int &now,int w,int lt,int rt){
37     now=++id;
38     tree[now].lt=lt,tree[now].rt=rt;
39     if(lt==rt){ tree[now].num=1;return ;}
40     int mid=lt+rt>>1;
41     if(w<=mid) build(tree[now].ch[0],w,lt,mid);
42     else build(tree[now].ch[1],w,mid+1,rt);
43     update(now);
44 }
45 
46 int ask(int now,int k){
47     if(tree[now].num<k) return -1;if(tree[now].lt==tree[now].rt) return tree[now].lt;
48     if(tree[tree[now].ch[0]].num>=k) return ask(tree[now].ch[0],k);
49     else return ask(tree[now].ch[1],k-tree[tree[now].ch[0]].num);
50 }
51 
52 int main(){
53     //freopen("1.in","r",stdin);
54     scanf("%d%d",&n,&m);
55     for(int i=1;i<=n;i++) fa[i]=i;
56     for(int i=1;i<=n;i++){
57         scanf("%d",&g[i]);f[g[i]]=i;
58         build(root[i],g[i],1,n);    
59     } int u,v,x,y,tt;
60     for(int i=1;i<=m;i++) scanf("%d%d",&u,&v),connect(u,v);
61     scanf("%d",&m);
62     for(int i=1;i<=m;i++){
63         scanf("%s%d%d",ch,&x,&y);
64         if(ch[0]=='Q') 
65             tt=ask(root[ffa(x)],y),printf("%d
",tt==-1?-1:f[tt]);
66         else connect(x,y);
67     }
68     return 0;
69 }
原文地址:https://www.cnblogs.com/tang666/p/8848156.html