Description

  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成

一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I

II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

  输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有

一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作

的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

  对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4

1 2

2 3

4 1

4 2 1 3

12

QMAX 3 4

QMAX 3 3

QMAX 3 2

QMAX 2 3

QSUM 3 4

QSUM 2 1

CHANGE 1 5

QMAX 3 4

CHANGE 3 6

QMAX 3 4

QMAX 2 4

QSUM 3 4

Sample Output

4

1

2

2

10

6

5

6

5

16

Solution

这题还是很水的

只要维护链上的信息,又是静态,没有加删边

所以LCT和树剖都可以做

这是LCT的代码:(自带大常数)

  1. #include<bits/stdc++.h>
  2. #define ui unsigned int
  3. #define ll long long
  4. #define db double
  5. #define ld long double
  6. #define ull unsigned long long
  7. const int MAXN=30000+10,inf=0x3f3f3f3f;
  8. int n,q;
  9. #define lc(x) ch[(x)][0]
  10. #define rc(x) ch[(x)][1]
  11. struct LCT{
  12. int ch[MAXN][2],fa[MAXN],rev[MAXN],val[MAXN],Mx[MAXN],Sm[MAXN],stack[MAXN],cnt;
  13. inline void init()
  14. {
  15. memset(Mx,-inf,sizeof(Mx));
  16. memset(val,-inf,sizeof(val));
  17. }
  18. inline bool nroot(int x)
  19. {
  20. return lc(fa[x])==x||rc(fa[x])==x;
  21. }
  22. inline void reverse(int x)
  23. {
  24. std::swap(lc(x),rc(x));
  25. rev[x]^=1;
  26. }
  27. inline void pushup(int x)
  28. {
  29. Sm[x]=(val[x]!=-inf?val[x]:0)+Sm[lc(x)]+Sm[rc(x)];
  30. Mx[x]=val[x];
  31. if(Mx[lc(x)]>Mx[x])Mx[x]=Mx[lc(x)];
  32. if(Mx[rc(x)]>Mx[x])Mx[x]=Mx[rc(x)];
  33. }
  34. inline void pushdown(int x)
  35. {
  36. if(rev[x])
  37. {
  38. if(lc(x))reverse(lc(x));
  39. if(rc(x))reverse(rc(x));
  40. rev[x]=0;
  41. }
  42. }
  43. inline void rotate(int x)
  44. {
  45. int f=fa[x],p=fa[f],c=(rc(f)==x);
  46. if(nroot(f))ch[p][rc(p)==f]=x;
  47. fa[ch[f][c]=ch[x][c^1]]=f;
  48. fa[ch[x][c^1]=f]=x;
  49. fa[x]=p;
  50. pushup(f);
  51. pushup(x);
  52. }
  53. inline void splay(int x)
  54. {
  55. cnt=0;
  56. stack[++cnt]=x;
  57. for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
  58. while(cnt)pushdown(stack[cnt--]);
  59. for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
  60. if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
  61. pushup(x);
  62. }
  63. inline void access(int x)
  64. {
  65. for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
  66. }
  67. inline void makeroot(int x)
  68. {
  69. access(x);splay(x);reverse(x);
  70. }
  71. inline void split(int x,int y)
  72. {
  73. makeroot(x);access(y);splay(y);
  74. }
  75. inline void link(int x,int y)
  76. {
  77. makeroot(x);fa[x]=y;
  78. }
  79. };
  80. LCT T;
  81. #undef lc
  82. #undef rc
  83. template<typename T> inline void read(T &x)
  84. {
  85. T data=0,w=1;
  86. char ch=0;
  87. while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
  88. if(ch=='-')w=-1,ch=getchar();
  89. while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
  90. x=data*w;
  91. }
  92. template<typename T> inline void write(T x,char c='\0')
  93. {
  94. if(x<0)putchar('-'),x=-x;
  95. if(x>9)write(x/10);
  96. putchar(x%10+'0');
  97. if(c!='\0')putchar(c);
  98. }
  99. template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
  100. template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
  101. template<typename T> inline T min(T x,T y){return x<y?x:y;}
  102. template<typename T> inline T max(T x,T y){return x>y?x:y;}
  103. int main()
  104. {
  105. read(n);
  106. T.init();
  107. for(register int i=1;i<n;++i)
  108. {
  109. int u,v;
  110. read(u);read(v);
  111. T.link(u,v);
  112. }
  113. for(register int i=1;i<=n;++i)T.access(i),T.splay(i),read(T.val[i]),T.pushup(i);
  114. read(q);
  115. while(q--)
  116. {
  117. char opt[8];int u,v;
  118. scanf("%s",opt);read(u);read(v);
  119. if(!strcmp(opt,"QMAX"))T.split(u,v),write(T.Mx[v],'\n');
  120. if(!strcmp(opt,"QSUM"))T.split(u,v),write(T.Sm[v],'\n');
  121. if(!strcmp(opt,"CHANGE"))T.access(u),T.splay(u),T.val[u]=v,T.pushup(u);
  122. }
  123. return 0;
  124. }

这是树剖的代码(老代码,以前的):

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define Mid ((l+r)>>1)
  5. #define lson rt<<1,l,Mid
  6. #define rson rt<<1|1,Mid+1,r
  7. const ll MAXN=30000+10;
  8. ll n,m,Mod,to[MAXN<<1],nex[MAXN<<1],beg[MAXN],fa[MAXN],Tre[MAXN],Val[MAXN],size[MAXN],Sum[MAXN<<2],Add[MAXN<<2],sta[MAXN],end[MAXN],hson[MAXN],cnt,e,dep[MAXN],top[MAXN],Max[MAXN<<2];
  9. inline void read(ll &x)
  10. {
  11. ll data=0,w=1;
  12. char ch=0;
  13. while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
  14. if(ch=='-')w=-1,ch=getchar();
  15. while(ch>='0'&&ch<='9')data=(data<<3)+(data<<1)+(ch^'0'),ch=getchar();
  16. x=data*w;
  17. }
  18. inline void insert(ll x,ll y)
  19. {
  20. to[++e]=y;
  21. nex[e]=beg[x];
  22. beg[x]=e;
  23. }
  24. inline void dfs1(ll x,ll f)
  25. {
  26. ll tmp=0;
  27. fa[x]=f;
  28. size[x]=1;
  29. dep[x]=dep[f]+1;
  30. for(register ll i=beg[x];i;i=nex[i])
  31. if(to[i]==f)continue;
  32. else
  33. {
  34. dfs1(to[i],x);
  35. size[x]+=size[to[i]];
  36. if(size[to[i]]>tmp)tmp=size[to[i]],hson[x]=to[i];
  37. }
  38. }
  39. inline void dfs2(ll x,ll head)
  40. {
  41. top[x]=head;
  42. sta[x]=++cnt;
  43. Val[cnt]=Tre[x];
  44. if(hson[x])dfs2(hson[x],head);
  45. for(register ll i=beg[x];i;i=nex[i])
  46. if(to[i]==fa[x]||to[i]==hson[x])continue;
  47. else dfs2(to[i],to[i]);
  48. end[x]=cnt;
  49. }
  50. inline void PushUp(ll rt)
  51. {
  52. Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];
  53. Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
  54. }
  55. inline void PushDown(ll rt,ll len)
  56. {
  57. Add[rt<<1]+=Add[rt];
  58. Add[rt<<1|1]+=Add[rt];
  59. Max[rt<<1]+=Add[rt];
  60. Max[rt<<1|1]+=Add[rt];
  61. Sum[rt<<1]+=Add[rt]*(len-(len>>1));
  62. Sum[rt<<1|1]+=Add[rt]*(len>>1);
  63. Add[rt]=0;
  64. }
  65. inline void Build(ll rt,ll l,ll r)
  66. {
  67. if(l==r)Sum[rt]=Val[l],Max[rt]=Val[l];
  68. else
  69. {
  70. Build(lson);
  71. Build(rson);
  72. PushUp(rt);
  73. }
  74. }
  75. inline void init()
  76. {
  77. dfs1(1,0);
  78. dfs2(1,1);
  79. Build(1,1,n);
  80. }
  81. inline void Update(ll rt,ll l,ll r,ll pos,ll k)
  82. {
  83. if(l==r&&r==pos)
  84. {
  85. Max[rt]=k;
  86. Sum[rt]=k;
  87. }
  88. else
  89. {
  90. if(Add[rt])PushDown(rt,r-l+1);
  91. if(pos<=Mid)Update(lson,pos,k);
  92. else if(pos>Mid)Update(rson,pos,k);
  93. PushUp(rt);
  94. }
  95. }
  96. inline ll Query(ll rt,ll l,ll r,ll L,ll R)
  97. {
  98. if(L<=l&&r<=R)return Sum[rt];
  99. else
  100. {
  101. if(Add[rt])PushDown(rt,r-l+1);
  102. ll tmp=0;
  103. if(L<=Mid)tmp+=Query(lson,L,R);
  104. if(R>Mid)tmp+=Query(rson,L,R);
  105. return tmp;
  106. }
  107. }
  108. inline ll Maxfind(ll rt,ll l,ll r,ll L,ll R)
  109. {
  110. if(L<=l&&r<=R)return Max[rt];
  111. else
  112. {
  113. if(Add[rt])PushDown(rt,r-l+1);
  114. ll tmp=-1e18;
  115. if(L<=Mid)tmp=max(tmp,Maxfind(lson,L,R));
  116. if(R>Mid)tmp=max(tmp,Maxfind(rson,L,R));
  117. return tmp;
  118. }
  119. }
  120. inline ll Getmax(ll x,ll y)
  121. {
  122. ll res=-1e18;
  123. while(top[x]!=top[y])
  124. if(dep[top[x]]>dep[top[y]])
  125. {
  126. res=max(Maxfind(1,1,n,sta[top[x]],sta[x]),res);
  127. x=fa[top[x]];
  128. }
  129. else
  130. {
  131. res=max(Maxfind(1,1,n,sta[top[y]],sta[y]),res);
  132. y=fa[top[y]];
  133. }
  134. res=max(res,Maxfind(1,1,n,min(sta[x],sta[y]),max(sta[x],sta[y])));
  135. return res;
  136. }
  137. inline ll Getans(ll x,ll y)
  138. {
  139. ll res=0;
  140. while(top[x]!=top[y])
  141. if(dep[top[x]]>dep[top[y]])
  142. {
  143. res+=Query(1,1,n,sta[top[x]],sta[x]);
  144. x=fa[top[x]];
  145. }
  146. else
  147. {
  148. res+=Query(1,1,n,sta[top[y]],sta[y]);
  149. y=fa[top[y]];
  150. }
  151. res+=Query(1,1,n,min(sta[x],sta[y]),max(sta[x],sta[y]));
  152. return res;
  153. }
  154. int main()
  155. {
  156. read(n);
  157. for(register ll i=1;i<n;++i)
  158. {
  159. ll u,v;
  160. read(u);read(v);
  161. insert(u,v);insert(v,u);
  162. }
  163. for(register ll i=1;i<=n;++i)read(Tre[i]);
  164. init();
  165. read(m);
  166. while(m--)
  167. {
  168. char str[10];
  169. scanf("%s",str);
  170. if(!strcmp(str,"QMAX"))
  171. {
  172. ll x,y;
  173. read(x);read(y);
  174. printf("%lld\n",Getmax(x,y));
  175. }
  176. else if(!strcmp(str,"QSUM"))
  177. {
  178. ll x,y;
  179. read(x);read(y);
  180. printf("%lld\n",Getans(x,y));
  181. }
  182. else if(!strcmp(str,"CHANGE"))
  183. {
  184. ll x,t;
  185. read(x);read(t);
  186. Update(1,1,n,sta[x],t);
  187. }
  188. }
  189. return 0;
  190. }

【刷题】BZOJ 1036 [ZJOI2008]树的统计Count的更多相关文章

  1. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  2. BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14982  Solved: 6081[Submit ...

  3. Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 11102  Solved: 4490[Submit ...

  4. 数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 12266  Solved: 4945[Submit ...

  5. bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 16294  Solved: 6645[Submit ...

  6. BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14302  Solved: 5779[Submit ...

  7. BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 14354  Solved: 5802 [Subm ...

  8. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit ...

  9. BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )

    树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...

  10. bzoj 1036: [ZJOI2008]树的统计Count (树链剖分+线段树 点权)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 21194  Solved: 8589[Submit ...

随机推荐

  1. 任务队列和异步接口的正确打开方式(.NET Core版本)

    任务队列和异步接口的正确打开方式 什么是异步接口? Asynchronous Operations Certain types of operations might require processi ...

  2. Ajax在Django中的应用

    一.什么是Ajax AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”.即使用Javascript语言与服务器进行异步交互,传 ...

  3. Arduino语言

    Arduino语言 Arduino语言是建立在C/C++基础上的,其实也就是基础的C语言,Arduino语言只不过把AVR单片机(微控制器)相关的一些参数设置都函数化,不用我们去了解他的底层,让我们不 ...

  4. 第四篇 Postman之Pre-request Script(前置处理器:JS之 YYYY-MM-DD HH:MM:SS)

    本篇来讲讲Pre-request Script 前置处理器,定义在发送request之前需要运行的一些脚本,应用场景主要是设置全局变量和环境变量. 本例子也是项目中遇到的,需要修改与客户的预约时间,但 ...

  5. Zabbix远程执行命令

    原文发表于cu:2016-06-14 Zabbix触发器(trigger)达到阀值后会有动作(action)执行:发送告警信息或执行远程命令. 本文主要配置验证zabbix执行远程命令. 一.环境 S ...

  6. 【python 3.6】python读取json数据存入MySQL(一)

    整体思路: 1,读取json文件 2,将数据格式化为dict,取出key,创建数据库表头 3,取出dict的value,组装成sql语句,循环执行 4,执行SQL语句 #python 3.6 # -* ...

  7. STC 单片机ADC实现原理

    模数转换器原理 数模转换器( analog to digitI converter,ADC),简称为A/D,ADC是链接模拟世界和数字世界的桥梁.它用于将连续的模拟信号转换为数字形式离散信号.典型的, ...

  8. ES6的新特性(15)——Promise 对象

    Promise 对象 Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了 ...

  9. Github三次学习

    作者声明:本文参照aicoder.com马伦老师的文档,根据自己的学习情况而做的笔记,仅供交流学习. Git入门到高级教程 为什么要进行项目文件的版本管理 代码备份和恢复 团队开发和协作流程 项目分支 ...

  10. npm 常用指令

    npm install <name>安装nodejs的依赖包 例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本, ...