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

首先这题意要求树链上的最大值以及求和,其树链剖分的做法已经昭然若揭

问题在于这次的信息有宗教条件下的限制,导致不那么容易维护。

第一个想法自然是对于每一个宗教都建一颗线段树,看一下数据范围,宗教的范围是1e5,N的范围也是1e5,又好像空间不那么允许。

事实上可以采用动态线段树的方法节省一波空间,整个做法就变得科学了起来。

如果不是因为我的愚蠢在树剖的重链部分写挂了导致T了很久,这题还是很温暖的

  1. #include <map>
  2. #include <set>
  3. #include <ctime>
  4. #include <cmath>
  5. #include <queue>
  6. #include <stack>
  7. #include <vector>
  8. #include <string>
  9. #include <cstdio>
  10. #include <cstdlib>
  11. #include <cstring>
  12. #include <sstream>
  13. #include <iostream>
  14. #include <algorithm>
  15. #include <functional>
  16. using namespace std;
  17. #define For(i, x, y) for(int i=x;i<=y;i++)
  18. #define _For(i, x, y) for(int i=x;i>=y;i--)
  19. #define Mem(f, x) memset(f,x,sizeof(f))
  20. #define Sca(x) scanf("%d", &x)
  21. #define Sca2(x,y) scanf("%d%d",&x,&y)
  22. #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
  23. #define Scl(x) scanf("%lld",&x);
  24. #define Pri(x) printf("%d\n", x)
  25. #define Prl(x) printf("%lld\n",x);
  26. #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
  27. #define LL long long
  28. #define ULL unsigned long long
  29. #define mp make_pair
  30. #define PII pair<int,int>
  31. #define PIL pair<int,long long>
  32. #define PLL pair<long long,long long>
  33. #define pb push_back
  34. #define fi first
  35. #define se second
  36. typedef vector<int> VI;
  37. int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
  38. while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
  39. const double eps = 1e-;
  40. const int maxn = 1e5 + ;
  41. const int INF = 0x3f3f3f3f;
  42. const int mod = 1e9 + ;
  43. int N,M,K;
  44. inline int max(int a,int b){
  45. return a>b?a:b;
  46. }
  47. PII node[maxn];
  48. struct Edge{
  49. int to,next;
  50. }edge[maxn * ];
  51. int head[maxn],Tot;
  52. void init(){
  53. for(int i = ; i <= N ; i ++) head[i] = -;
  54. Tot = ;
  55. }
  56. void add(int u,int v){
  57. edge[Tot].to = v;
  58. edge[Tot].next = head[u];
  59. head[u] = Tot++;
  60. }
  61. int size[maxn],top[maxn],fa[maxn],son[maxn];
  62. int dep[maxn],pos[maxn];
  63. void dfs(int t,int la){
  64. size[t] = ; son[t] = ;
  65. int heavy = ;
  66. for(int i = head[t]; ~i ; i = edge[i].next){
  67. int v = edge[i].to;
  68. if(v == la) continue;
  69. fa[v] = t;
  70. dep[v] = dep[t] + ;
  71. dfs(v,t);
  72. if(heavy < size[v]){
  73. heavy = size[v];
  74. son[t] = v;
  75. }
  76. size[t] += size[v];
  77. }
  78. }
  79. int cnt;
  80. void dfs2(int t,int la){
  81. top[t] = la;
  82. pos[t] = ++cnt;
  83. if(!son[t]) return;
  84. dfs2(son[t],la);
  85. for(int i = head[t]; ~i ; i = edge[i].next){
  86. int v = edge[i].to;
  87. if(fa[t] == v || son[t] == v) continue;
  88. dfs2(v,v);
  89. }
  90. }
  91. struct Tree{
  92. int Max,sum;
  93. int lt,rt;
  94. void init(){
  95. Max = sum = lt = rt = ;
  96. }
  97. }tree[maxn * ];
  98. int tot;
  99. int thead[maxn];
  100. void check(int &t){
  101. if(t) return;
  102. t = ++tot;
  103. tree[t].init();
  104. }
  105. void Pushup(int t){
  106. int ls = tree[t].lt,rs = tree[t].rt;
  107. check(ls);check(rs);
  108. tree[t].sum = tree[ls].sum + tree[rs].sum;
  109. tree[t].Max = max(tree[ls].Max,tree[rs].Max);
  110. }
  111. void update(int &t,int l,int r,int p,int w){
  112. check(t);
  113. if(l == r){
  114. tree[t].Max = tree[t].sum = w;
  115. return;
  116. }
  117. int m = (l + r) >> ;
  118. if(p <= m) update(tree[t].lt,l,m,p,w);
  119. else update(tree[t].rt,m + ,r,p,w);
  120. Pushup(t);
  121. }
  122. void update(int i,int w){
  123. update(thead[node[i].se],,N,pos[i],w);
  124. }
  125. int query(int &t,int l,int r,int L,int R,int p){
  126. check(t);
  127. if(L <= l && r <= R){
  128. if(p) return tree[t].sum;
  129. else return tree[t].Max;
  130. }
  131. int m = (l + r) >> ;
  132. if(R <= m) return query(tree[t].lt,l,m,L,R,p);
  133. else if(L > m) return query(tree[t].rt,m + ,r,L,R,p);
  134. else{
  135. if(p) return query(tree[t].lt,l,m,L,m,p) + query(tree[t].rt,m + ,r,m + ,R,p);
  136. else return max(query(tree[t].lt,l,m,L,m,p),query(tree[t].rt,m + ,r,m + ,R,p));
  137. }
  138. }
  139. int query(int u,int v,int flag){
  140. int ans = ;
  141. int &c = thead[node[u].se];
  142. while(top[u] != top[v]){
  143. if(dep[top[u]] < dep[top[v]]) swap(u,v);
  144. if(flag) ans += query(c,,N,pos[top[u]],pos[u],);
  145. else ans = max(ans,query(c,,N,pos[top[u]],pos[u],));
  146. u = fa[top[u]];
  147. }
  148. if(dep[u] > dep[v]) swap(u,v);
  149. if(flag) ans += query(c,,N,pos[u],pos[v],);
  150. else ans = max(ans,query(c,,N,pos[u],pos[v],));
  151. return ans;
  152. }
  153. int main(){
  154. Sca2(N,M); init();
  155. for(int i = ; i <= N ; i ++) node[i].fi = read(),node[i].se = read();
  156. for(int i = ; i <= N - ; i ++){
  157. int u = read(),v = read();
  158. add(u,v); add(v,u);
  159. }
  160. int root = ;
  161. dfs(root,); dfs2(root,root);
  162. for(int i = ; i <= N; i ++) update(i,node[i].fi);
  163. for(int i = ; i <= M ; i ++){
  164. char op[];
  165. scanf("%s",op);
  166. int x = read(),y = read();
  167. if(op[] == 'C'){
  168. if(op[] == 'C'){
  169. update(x,);
  170. node[x].se = y;
  171. update(x,node[x].fi);
  172. }else{
  173. node[x].fi = y;
  174. update(x,y);
  175. }
  176. }else{
  177. if(op[] == 'S'){
  178. Pri(query(x,y,)); //sum
  179. }else{
  180. Pri(query(x,y,)); //Max
  181. }
  182. }
  183. }
  184. return ;
  185. }

BZOJ3531 树剖 + 动态开点线段树的更多相关文章

  1. BZOJ 3531: [Sdoi2014]旅行 (树剖+动态开点线段树)

    对于每种信仰维护一棵动态开点线段树就行了- #include <cstdio> #include <cctype> #include <cstring> #incl ...

  2. CF915E Physical Education Lessons 动态开点线段树

    题目链接 CF915E Physical Education Lessons 题解 动态开点线段树 代码 /* 动态开点线段树 */ #include<cstdio> #include&l ...

  3. bzoj3531: [Sdoi2014]旅行 (树链剖分 && 动态开点线段树)

    感觉动态开点线段树空间复杂度好优秀呀 树剖裸题 把每个宗教都开一颗线段树就可以了 但是我一直TLE 然后调了一个小时 为什么呢 因为我 #define max(x, y) (x > y ? x ...

  4. NFLSOJ #917 -「lych_cys模拟题2018」橘子树(树剖+ODT+莫反统计贡献的思想+动态开点线段树)

    题面传送门 sb 出题人不在题面里写 \(b_i=0\) 导致我挂成零蛋/fn/fn 首先考虑树链剖分将路径问题转化为序列上的问题,因此下文中简称"位置 \(i\)"表示 DFS ...

  5. [ZJOI2019]语言(树链剖分+动态开点线段树+启发式合并)

    首先,对于从每个点出发的路径,答案一定是过这个点的路径所覆盖的点数.然后可以做树上差分,对每个点记录路径产生总贡献,然后做一个树剖维护,对每个点维护一个动态开点线段树.最后再从根节点开始做一遍dfs, ...

  6. [2016湖南长沙培训Day4][前鬼后鬼的守护 chen] (动态开点线段树+中位数 or 动规 or 贪心+堆优化)

    题目大意 给定一个长度为n的正整数序列,令修改一个数的代价为修改前后两个数的绝对值之差,求用最小代价将序列转换为不减序列. 其中,n满足小于500000,序列中的正整数小于10^9 题解(引自mzx神 ...

  7. [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...

  8. 【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化

    4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 247  Solved: 113[Submit][Status][Discuss ...

  9. codeforces 893F - Physical Education Lessons 动态开点线段树合并

    https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...

随机推荐

  1. 转载:实现MATLAB2016a和M文件关联

    转载自http://blog.csdn.net/qq_22186119 新安装MATLAB2016a之后,发现MATLAB没有和m文件关联 每次打开m文件后都会重新打开一次MATLAB主程序 后来发现 ...

  2. hdu-1176(dp)

    解题思路:用dp做的,dp[i][j]表示在i时刻,j点的最大馅饼.a[i][j]表示在i这个时刻j点同时掉落的馅饼: 每个点除了0和10之外,都有三种状态: 1.没有移动,这样值就为dp[i][j] ...

  3. git使用常见问题

    1.git branch使用,创建新的分之后做修改后,其他分支也被同步修改 问题: 原项目在 master 分支,执行下面的操作:  git branch test  git checkout tes ...

  4. 洛谷p2661信息传递题解

    题目 这个题一眼看上去就是用并查集求最小环. 我们可以设两个数组分别是f,d分别表示该点的爸爸和该点到祖先的距离. 当该点的爸爸等于他时,那他肯定就是祖先. 此时信息就肯定传递完了,此时的整个图中(我 ...

  5. 【hdu6186】CS Course(前缀后缀异或)

    2017ACM/ICPC广西邀请赛 重现赛1005CS Course 题意 给一个数列a,每次询问去掉第p个的与和.或和,异或和. 题解 预处理前缀和.后缀和即可. 但是当时想都没想就写了个线段树.线 ...

  6. 【题解】 bzoj3693: 圆桌会议 (线段树+霍尔定理)

    bzoj3693 Solution: 显然我们可以把人和位置抽象成点,就成了一个二分图,然后就可以用霍尔定理判断是否能有解 一开始我随便YY了一个\(check\)的方法:就是每次向后一组,我们就把那 ...

  7. Python变量与赋值

    Python是一门独特的语言,与C语言有很大区别,初学Python很多萌新表示对变量与赋值不理解,学过C的都知道,给变量赋值时,需要先指定数据类型,同时会开辟一块内存区域,用于存储值,例如: int ...

  8. hexo从零开始

    部署Hexo Hexo官方文档 新建一个文件夹,比如,Blog,然后进入该文件夹下: npm install hexo-cli -g hexo version 安装依赖包 npm install 配置 ...

  9. Vue中的slot内容分发

    ①概述: 简单来说,假如父组件需要在子组件内放一些DOM,那么这些DOM是显示.不显示.在哪个地方显示.如何显示,就是slot分发负责的活. ②默认情况下 父组件在子组件内套的内容,是不显示的. 例如 ...

  10. luogu3242 接水果 (整体二分+树状数组)

    考虑整体二分,问题就变成了每个(水果)路径有多少个满足条件(权值)的(盘子)子路径 考虑一个盘子(a,b)表示两端点(不妨设dfn[a]<dfn[b]),那么他能接到的水果(u,v)一定满足(不 ...