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
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
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 }