【题目链接】

点击打开链接

【算法】

树链剖分

【代码】

本题,笔者求最近公共祖先并没有用树链剖分“往上跳”的方式,而是用倍增法。笔者认为这样比较好写,代码可读性

比较高

此外,笔者的线段树并没有用懒惰标记,只要当前访问节点的线段总数为1,那么就下传

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define MAXLOG 18
  4. const int MAXN = 1e5 + ;
  5.  
  6. int i,n,m,timer,x,y,c,t;
  7. int dep[MAXN],fa[MAXN],size[MAXN],son[MAXN],
  8. dfn[MAXN],top[MAXN],val[MAXN],pos[MAXN],anc[MAXN][MAXLOG];
  9. vector<int> e[MAXN];
  10. char opt[];
  11.  
  12. struct SegmentTree {
  13. struct Node {
  14. int l,r,sum,lcover,rcover;
  15. } Tree[MAXN*];
  16. inline void push_up(int index) {
  17. Tree[index].lcover = Tree[index<<].lcover;
  18. Tree[index].rcover = Tree[index<<|].rcover;
  19. Tree[index].sum = Tree[index<<].sum + Tree[index<<|].sum;
  20. if (Tree[index<<].rcover == Tree[index<<|].lcover) Tree[index].sum--;
  21. }
  22. inline void push_down(int index) {
  23. Tree[index<<].sum = Tree[index<<|].sum = ;
  24. Tree[index<<].lcover = Tree[index<<].rcover = Tree[index].lcover;
  25. Tree[index<<|].lcover = Tree[index<<|].rcover = Tree[index].rcover;
  26. }
  27. inline void build(int index,int l,int r) {
  28. int mid;
  29. Tree[index].l = l;
  30. Tree[index].r = r;
  31. if (l == r) {
  32. Tree[index].lcover = Tree[index].rcover = val[pos[l]];
  33. Tree[index].sum = ;
  34. return;
  35. }
  36. mid = (l + r) >> ;
  37. build(index<<,l,mid);
  38. build(index<<|,mid+,r);
  39. push_up(index);
  40. }
  41. inline void modify(int index,int l,int r,int val) {
  42. int mid;
  43. if (Tree[index].l == l && Tree[index].r == r) {
  44. Tree[index].lcover = Tree[index].rcover = val;
  45. Tree[index].sum = ;
  46. return;
  47. }
  48. if (Tree[index].sum == ) push_down(index);
  49. mid = (Tree[index].l + Tree[index].r) >> ;
  50. if (mid >= r) modify(index<<,l,r,val);
  51. else if (mid + <= l) modify(index<<|,l,r,val);
  52. else {
  53. modify(index<<,l,mid,val);
  54. modify(index<<|,mid+,r,val);
  55. }
  56. push_up(index);
  57. }
  58. inline int query(int index,int l,int r) {
  59. int mid,t;
  60. if (Tree[index].l == l && Tree[index].r == r) return Tree[index].sum;
  61. if (Tree[index].sum == ) push_down(index);
  62. mid = (Tree[index].l + Tree[index].r) >> ;
  63. if (mid >= r) return query(index<<,l,r);
  64. else if (mid + <= l) return query(index<<|,l,r);
  65. else {
  66. t = ;
  67. if (Tree[index<<].rcover == Tree[index<<|].lcover) t = ;
  68. return query(index<<,l,mid) + query(index<<|,mid+,r) - t;
  69. }
  70. }
  71. inline int get(int index,int pos) {
  72. int mid;
  73. if (Tree[index].l == Tree[index].r) return Tree[index].lcover;
  74. if (Tree[index].sum == ) push_down(index);
  75. mid = (Tree[index].l + Tree[index].r) >> ;
  76. if (mid >= pos) return get(index<<,pos);
  77. else return get(index<<|,pos);
  78. }
  79. } T;
  80. inline void dfs1(int x) {
  81. int i,y;
  82. anc[x][] = fa[x];
  83. for (i = ; i < MAXLOG; i++) {
  84. if (dep[x] < ( << i)) break;
  85. anc[x][i] = anc[anc[x][i-]][i-];
  86. }
  87. size[x] = ;
  88. for (i = ; i < e[x].size(); i++) {
  89. y = e[x][i];
  90. if (fa[x] != y) {
  91. dep[y] = dep[x] + ;
  92. fa[y] = x;
  93. dfs1(y);
  94. size[x] += size[y];
  95. if (size[y] > size[son[x]]) son[x] = y;
  96. }
  97. }
  98. }
  99. inline void dfs2(int x,int tp) {
  100. int i,y;
  101. dfn[x] = ++timer;
  102. pos[timer] = x;
  103. top[x] = tp;
  104. if (son[x]) dfs2(son[x],tp);
  105. for (i = ; i < e[x].size(); i++) {
  106. y = e[x][i];
  107. if (fa[x] != y && son[x] != y)
  108. dfs2(y,y);
  109. }
  110. }
  111. inline int lca(int x,int y) {
  112. int i,t;
  113. if (dep[x] > dep[y]) swap(x,y);
  114. t = dep[y] - dep[x];
  115. for (i = ; i <= MAXLOG - ; i++) {
  116. if (t & ( << i))
  117. y = anc[y][i];
  118. }
  119. if (x == y) return x;
  120. for (i = MAXLOG - ; i >= ; i--) {
  121. if (anc[x][i] != anc[y][i]) {
  122. x = anc[x][i];
  123. y = anc[y][i];
  124. }
  125. }
  126. return anc[x][];
  127. }
  128. inline void modify(int x,int y,int c) {
  129. int tx = top[x],
  130. ty = top[y];
  131. while (tx != ty) {
  132. T.modify(,dfn[tx],dfn[x],c);
  133. x = fa[tx]; tx = top[x];
  134. }
  135. T.modify(,dfn[y],dfn[x],c);
  136. }
  137. inline int query(int x,int y) {
  138. int tx = top[x],
  139. ty = top[y],ans = ;
  140. while (tx != ty) {
  141. ans += T.query(,dfn[tx],dfn[x]);
  142. if (T.get(,dfn[tx]) == T.get(,dfn[fa[tx]])) ans--;
  143. x = fa[tx]; tx = top[x];
  144. }
  145. ans += T.query(,dfn[y],dfn[x]);
  146. return ans;
  147. }
  148.  
  149. int main() {
  150.  
  151. scanf("%d%d",&n,&m);
  152. for (i = ; i <= n; i++) scanf("%d",&val[i]);
  153. for (i = ; i < n; i++) {
  154. scanf("%d%d",&x,&y);
  155. e[x].push_back(y);
  156. e[y].push_back(x);
  157. }
  158.  
  159. dfs1();
  160. dfs2(,);
  161. T.build(,,timer);
  162.  
  163. while (m--) {
  164. scanf("%s",opt);
  165. if (opt[] == 'C') {
  166. scanf("%d%d%d",&x,&y,&c);
  167. t = lca(x,y);
  168. modify(x,t,c); modify(y,t,c);
  169. } else {
  170. scanf("%d%d",&x,&y);
  171. t = lca(x,y);
  172. printf("%d\n",query(x,t)+query(y,t)-);
  173. }
  174. }
  175.  
  176. return ;
  177. }

【SDOI 2011】染色的更多相关文章

  1. [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】

    题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...

  2. BZOJ 2243 SDOI 2011染色

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 算法讨论: 树链剖分把树放到线段树上.然后线段树的每个节点要维护的东西有左端点的颜色 ...

  3. [SDOI 2011]染色

    Description 题库链接 给定一棵有 \(n\) 个节点的无根树和 \(m\) 个操作,操作有 \(2\) 类: 将节点 \(a\) 到节点 \(b\) 路径上所有点都染成颜色 \(c\) : ...

  4. 解题: SDOI 2011 染色

    题面 强行把序列问题通过树剖套在树上...算了算是回顾了一下树剖的思想=.= 每次树上跳的时候注意跳的同时维护当前拼出来的左右两条链的靠上的端点,然后拼起来的时候讨论一下拼接点,最后一下左右两边的端点 ...

  5. 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法

    BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...

  6. [bzoj2286][Sdoi 2011]消耗战

    [bzoj2286]消耗战 标签: 虚树 DP 题目链接 题解 很容易找出\(O(mn)\)的做法. 只需要每次都dp一遍. 但是m和n是同阶的,所以这样肯定会T的. 注意到dp的时候有很多节点是不需 ...

  7. [SDOI 2011]黑白棋

    Description 题库链接 给出一个 \(1\times n\) 的棋盘,棋盘上有 \(k\) 个棋子,一半是黑色,一半是白色.最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 \( ...

  8. [SDOI 2011]消耗战

    Description 题库链接 给你一棵 \(n\) 个节点根节点为 \(1\) 的有根树,有边权. \(m\) 次询问,每次给出 \(k_i\) 个关键点.询问切断一些边,使这些点到根节点不连通, ...

  9. [SDOI 2011]计算器

    Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给 ...

随机推荐

  1. linux基础知识汇总

    1.如何快速回到上次操作的目录? cd - 2.如何快速回到家目录? 直接cd或者cd ~ 3.怎么回到上一级目录? cd .. 4.什么是相对路径,什么是绝对路径? 相对路径就是相对于当前目录的位置 ...

  2. 1597: [Usaco2008 Mar]土地购买 [ dp+斜率优化 ] 未完

    传送门 1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1979  Solved: 705[Subm ...

  3. iOS 调用系统相册 相机 时,显示中文标题

    解决手机语言已经设置显示中文 在调用系统相册.相机界面 时显示英文问题, 在 info.plist里面添加Localized resources can be mixed YES 表示是否允许应用程序 ...

  4. 从零开始写STL—functional

    function C++11 将任意类型的可调用(Callable)对象与函数调用的特征封装到一起. 这里的类是对函数策略的封装,将函数的性质抽象成组件,便于和algorithm库配合使用 基本运算符 ...

  5. C. Day at the Beach---cf559

    http://codeforces.com/problemset/problem/599/C 题目大意: 有n个城堡的高度   让你最多分成几个块   每个块排过序之后 整体是按照升序来的 分析:   ...

  6. codevs——1269 匈牙利游戏

    1269 匈牙利游戏 2012年CCC加拿大高中生信息学奥赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Descript ...

  7. poj——1274 The Perfect Stall

    poj——1274   The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25709   A ...

  8. 转: 关于Linux常用的二进制文件分析方法

    当你在unix下拿到一个二进制文件但不知道它是什么的时候,可以通过以下方法得到一此提示 1. 最首先应该尝试strings命令,比如拿到一个叫cr1的二进制文件,可以: $ strings cr1 | ...

  9. 使用图像扫描控件ScanOnWeb实现在线图像扫描

    今天上网查资料,看到一篇文章,描述的是一个开发OA软件的公司解决浏览器嵌入式扫描仪编程的文章,文章描述了改OA厂商的工程师如何辛苦的克服了各种技术难题,最终实现了在线图像扫描处理,然后又在无数个不眠的 ...

  10. HDU 4279 Number(找规律)

    Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...