Description

Input

第一行包含一个正整数testcase,表示当前测试数据的测试点编号。保证1≤testcase≤20。
第二行包含三个整数N,M,T,分别表示节点数、初始边数、操作数。第三行包含N个非负整数表示 N个节点上的权值。
 接下来 M行,每行包含两个整数x和 y,表示初始的时候,点x和点y 之间有一条无向边, 接下来 T行,每行描述一个操作,格式为“Q x y k”或者“L x y ”,其含义见题目描述部分。

Output

对于每一个第一类操作,输出一个非负整数表示答案。

Sample Input

1
8 4 8
1 1 2 2 3 3 4 4
4 7
1 8
2 4
2 1
Q 8 7 3 Q 3 5 1
Q 10 0 0
L 5 4
L 3 2 L 0 7
Q 9 2 5 Q 6 1 6

Sample Output

2
2
1
4
2

HINT

对于第一个操作 Q 8 7 3,此时 lastans=0,所以真实操作为Q 8^0 7^0 3^0,也即Q 8 7 3。点8到点7的路径上一共有5个点,其权值为4 1 1 2 4。这些权值中,第三小的为 2,输出 2,lastans变为2。对于第二个操作 Q 3 5 1 ,此时lastans=2,所以真实操作为Q 3^2 5^2 1^2 ,也即Q 1 7 3。点1到点7的路径上一共有4个点,其权值为 1 1 2 4 。这些权值中,第三小的为2,输出2,lastans变为 2。之后的操作类似。

【思路】

主席树+倍增lca+启发式合并

如果没有连边操作的话就是luo主席树。两棵树要相连,那一棵在上面无所谓,因为我们要遍历处于下方的树的所有节点所以我们采用启发式合并,即每次选择结点数更小的树放在下面,然后重建每一个结点。

【代码】

  1. #include<cmath>
  2. #include<queue>
  3. #include<vector>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<iostream>
  7. #include<algorithm>
  8. #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
  9. using namespace std;
  10.  
  11. const int N = ;
  12. const int M = *N;
  13. const int D = ;
  14.  
  15. struct Tnode {
  16. int sum,lc,rc;
  17. } T[M];
  18.  
  19. int n,m,q,sz,rt[N];
  20. int p[N],siz[N];
  21. int fa[N][D],hash[N],dep[N];
  22. int v[N],tot;
  23. vector<int> g[N];
  24.  
  25. void read(int& x) {
  26. char c=getchar();
  27. int f=;x=;
  28. while(!isdigit(c)) {
  29. if(c=='-') f=-; c=getchar();
  30. }
  31. while(isdigit(c))
  32. x=x*+c-'',c=getchar();
  33. x*=f;
  34. }
  35.  
  36. int ifind(int u)
  37. {
  38. while(fa[u][]) u=fa[u][];
  39. return u;
  40. }
  41. void insert(int l,int r,int x,int& y,int num)
  42. {
  43. T[y=++sz]=T[x]; T[y].sum++;
  44. if(l==r) return ;
  45. int mid=(l+r)>>;
  46. if(num<=mid) insert(l,mid,T[x].lc,T[y].lc,num);
  47. else insert(mid+,r,T[x].rc,T[y].rc,num);
  48. }
  49. void dfs(int u,int f)
  50. {
  51. dep[u]=dep[f]+; fa[u][]=f; siz[u]=;
  52. insert(,tot,rt[f],rt[u],v[u]);
  53. FOR(i,,D-) //p1
  54. fa[u][i]=fa[fa[u][i-]][i-];
  55. FOR(i,,(int)g[u].size()-) {
  56. int v=g[u][i];
  57. if(v!=f) {
  58. dfs(v,u);
  59. siz[u]+=siz[v];
  60. }
  61. }
  62. }
  63. int lca(int u,int v)
  64. {
  65. if(dep[u]<dep[v]) swap(u,v);
  66. int t=dep[u]-dep[v];
  67. FOR(j,,D-)
  68. if(t&(<<j)) u=fa[u][j];
  69. if(u==v) return u;
  70. for(int j=D-;j>=;j--)
  71. if(fa[u][j]!=fa[v][j]) u=fa[u][j],v=fa[v][j];
  72. return fa[u][];
  73. }
  74. int query(int l,int r,int a,int b,int c,int d,int rk)
  75. {
  76. if(l==r) return l;
  77. int mid=(l+r)>>;
  78. int now=T[T[a].lc].sum+T[T[b].lc].sum-T[T[c].lc].sum-T[T[d].lc].sum;
  79. if(rk<=now) return query(l,mid,T[a].lc,T[b].lc,T[c].lc,T[d].lc,rk);
  80. else return query(mid+,r,T[a].rc,T[b].rc,T[c].rc,T[d].rc,rk-now);
  81. }
  82. int query(int x,int y,int z)
  83. {
  84. int c=lca(x,y);
  85. return query(,tot,rt[x],rt[y],rt[c],rt[fa[c][]],z);
  86. }
  87.  
  88. int main()
  89. {
  90. int kase; read(kase);
  91. read(n),read(m),read(q);
  92. FOR(i,,n) {
  93. read(v[i]); hash[i]=v[i];
  94. fa[i][]=;
  95. }
  96. sort(hash+,hash+n+);
  97. tot=unique(hash+,hash+n+)-hash-;
  98. FOR(i,,n)
  99. v[i]=lower_bound(hash+,hash+tot+,v[i])-hash;
  100. char op[];
  101. int ans=,x,y,z;
  102. FOR(i,,m) {
  103. read(x),read(y);
  104. g[x].push_back(y);
  105. g[y].push_back(x);
  106. }
  107. FOR(i,,n) if(!fa[i][]) dfs(i,);
  108. FOR(i,,q) {
  109. scanf("%s",op);
  110. read(x),read(y);
  111. x^=ans; y^=ans;
  112. if(op[]=='Q') {
  113. read(z);
  114. z^=ans;
  115. printf("%d\n",ans=hash[query(x,y,z)]);
  116. } else {
  117. int fx=ifind(x),fy=ifind(y);
  118. if(siz[fx]<siz[fy])
  119. swap(fx,fy),swap(x,y);
  120. siz[fx]+=siz[fy];
  121. g[x].push_back(y);
  122. g[y].push_back(x);
  123. dfs(y,x);
  124. }
  125. }
  126. return ;
  127. }

bzoj 3123 [Sdoi2013]森林(主席树,lca,启发式合并)的更多相关文章

  1. BZOJ3123[Sdoi2013]森林——主席树+LCA+启发式合并

    题目描述 输入 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负 ...

  2. BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]

    3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...

  3. Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...

  4. luoguP3302 [SDOI2013]森林 主席树 启发式合并

    题目链接 luoguP3302 [SDOI2013]森林 题解 本来这题树上主席树暴力启发式合并就完了 结果把lca写错了... 以后再也不这么写了 复杂度\(O(nlog^2n)\) "f ...

  5. bzoj 3123 [Sdoi2013]森林(主席树+启发式合并+LCA)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  6. 【BZOJ3123】[Sdoi2013]森林 主席树+倍增LCA+启发式合并

    [BZOJ3123][Sdoi2013]森林 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整 ...

  7. [BZOJ3123][Sdoi2013]森林 主席树+启发式合并

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当 ...

  8. ●BZOJ 3123 [Sdoi2013]森林

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3123 题解: 主席树,在线,启发式合并 简单版(只有询问操作):[2588: Spoj 10 ...

  9. bzoj 3123: [Sdoi2013]森林(45分暴力)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4184  Solved: 1235[Submit][Status ...

随机推荐

  1. CQRS学习——集成ASP.NET Identity[其五]

    [其实和Cqrs没啥关系] 缘由 其实没啥原因,只是觉得以前写了不知多少遍的用户登录复用性太差,实现的功能也不多. 依赖的Nuget包 简单登陆 就简单登陆而言,只需要实现如下接口/抽象类: Stor ...

  2. hibernate一对一双向外键关联

    一对一双向外键关联:双方都持有对方的外键关联关系. 主控方和一对一单向外键关联的情况是一样的,主要的差异表现为,被空方需要添加: @OneToOne(mappedBy="card" ...

  3. KafkaSpout: PartitionManager的行为分析

    KafkaSpout的核心逻辑都是由PartitionManager来实现的. 但是这个类实现时候需要考虑的东西有些多,0.92至0.93,至当前(2015.3.14)的master一直在变化.在这里 ...

  4. 成功解决Tomcat-JDBC-MySQL乱码

    0.MySQL-JDBC驱动文档 官方解释 1.数据库的字符编码和表内字段的编码 在MySQL中数据库的字符编码和表内字段的编码的要指定为utf8(utf8_general_ci) 2.jsp中 pa ...

  5. 程序自动生成Dump文件

    前言:通过drwtsn32.NTSD.CDB等调试工具生成Dump文件, drwtsn32存在的缺点虽然NTSD.CDB可以完全解决,但并不是所有的操作系统中都安装了NTSD.CDB等调试工具.了解了 ...

  6. CURL与PHP-CLI的应用【CLI篇】

    CLI的普通应用 什么是PHP-CLI php-cli是php Command Line Interface的简称,即PHP命令行接口,在windows和linux下都是支持PHP-CLI模式的; 为 ...

  7. php中对共享内存,消息队列的操作

    http://www.cnblogs.com/fengwei/archive/2012/09/12/2682646.html php作为脚本程序,通常生命周期都很短,如在web应用中,一次请求就是ph ...

  8. Oracle10g 回收站及彻底删除table : drop table xx purge

    drop后的表被放在回收站(user_recyclebin)里,而不是直接删除掉.这样,回收站里的表信息就可以被恢复,或彻底清除. 1.通过查询回收站user_recyclebin获取被删除的表信息, ...

  9. 关于fedora下jdk的安装

    http://zhumeng8337797.blog.163.com/blog/static/1007689142012472620637/ alternative命令 http://blog.csd ...

  10. C#中this在构造函数时的使用

    今天编程的时候,想要用this来处理构造函数,想了半天没有想起来 后来找了自己以前记录的 http://www.cnblogs.com/chucklu/p/4842766.html public Cu ...