bzoj5214 可持久化权值妹子树

Description

小y有n个妹子,编号分别为1, 2,... n。为了更好管理这些妹子,小y想把他们分成若干组~
 
在开始的开始(我们记作分组方案0)中,每个妹子各成一组。
每次小y会选择一个已有的分组方案i,挑出其中两个不在同组的妹子x, y,将她们所在的组合并。
我们将第j次操作得到的分组方案记作分组方案j。这样就可以得到许多不同的分组方案啦!
 
 
为了知道这些分组方案孰优孰劣,因此小y想知道关于分组方案的一些信息。
每次,小y会选择某一个分组方案i,询问x所在的组中编号第k小的妹子是谁。
 
 
为了小y的幸福(划掉),来帮帮他把(逃

 

Input

第一行两个整数n, m。表示妹子数和操作数。
接下来的m行,首先有一个整数opt。
如果opt=0,接下来三个整数i, x, y,表示一次合并。保证分组方案i已经出现过,x, y在不同组中。
如果opt=1,接下来三个整数i, x, k,表示一次询问。保证x所在的组中至少有k个妹子。
1 <=n, q <= 100000,合并不超过60000次,询问不超过60000次

 

Output

对于每个询问操作输出一个整数,表示该妹子的编号

 

Sample Input

3 6
0 0 1 2
1 1 1 2
1 1 2 1
0 1 2 3
0 1 1 3
1 3 3 2

Sample Output

2
1
2
 
思路: 根据时间关系建立操作树,然后对每个联通块的权值进行分块(方便查找答案),同loj519 
 1 #include<bits/stdc++.h>
 2 using namespace std;  
 3 #define bl(x)  ((x-1)/B+1)  
 4 #define st(x)  ((x-1)*B+1)  
 5 #define ed(x)  min(n,x*B)   
 6 int const N=200000+10; 
 7 int const B=350;    
 8 int f[N],a[N],cnt[N][350],n,m,sum,h[N],sz[N],ans[N];  
 9 struct edge{int to,nt;}e[N];   
10 struct query{int opt,x,y,id;}q[N];  
11 int cmp(int x,int y){return a[x]<a[y];}
12 int gf(int x){return x==f[x]?  x:gf(f[x]); }
13 void add(int a,int b){e[++sum].to=b;  e[sum].nt=h[a]; h[a]=sum; }
14 int query(int x,int y){
15     int fx=gf(x),k=1;  
16     for(int i=1;i<350;i++,k++)  
17         if(y>cnt[fx][i]) y-=cnt[fx][i];  
18         else break;   
19     for(int i=st(k);i<=ed(k);i++) 
20         if(gf(i)==fx){
21             if(!--y) { 
22                 return i;  
23             }
24         }
25 }
26 void dfs(int x){
27     int fx,fy;  
28     if(x && q[x].opt==0){
29         fx=gf(q[x].x);  
30         fy=gf(q[x].y);  
31         if(sz[fx]>sz[fy])  
32             swap(fx,fy);  
33         if(fx!=fy){
34             f[fx]=fy;  
35             for(int i=1;i<350;i++) cnt[fy][i]+=cnt[fx][i];  
36             sz[fy]+=sz[fx];  
37         }
38     }
39     if(q[x].opt==1){
40         ans[x-100000]=query(q[x].x,q[x].y);   
41     }
42     for(int i=h[x];i;i=e[i].nt)  
43         dfs(e[i].to);  
44     if(x && q[x].opt==0){
45         if(fx!=fy){
46             f[fx]=fx; 
47             sz[fy]-=sz[fx];  
48             for(int i=1;i<350;i++) cnt[fy][i]-=cnt[fx][i];  
49         }
50     }
51 }
52 int main(){
53     scanf("%d%d",&n,&m);  
54     for(int i=1;i<=n;i++) a[i]=i;   
55     int t=0; 
56     for(int i=1;i<=m;i++){
57         int opt,x,y,k; 
58         scanf("%d%d%d%d",&q[i].opt,&q[i].id,&q[i].x,&q[i].y);  
59         if(q[i].opt==0){
60             add(q[i].id,++t);  
61             q[t]=q[i];   
62         }else {
63             add(q[i].id,i+100000);      
64             q[i+100000]=q[i];  
65         }
66     }
67     for(int i=1;i<=n;i++) 
68         f[i]=i,sz[i]=1,cnt[i][bl(a[i])]++; 
69     dfs(0);  
70     for(int i=100001;i<=m+100000;i++)  
71         if(q[i].opt==1) printf("%d\n",ans[i-100000]); 
72     return 0; 
73 }
View Code

 

posted @ 2019-09-03 20:06  zjxxcn  阅读(158)  评论(0编辑  收藏  举报