BZOJ1036 树的统计Count(LCT动态树)
2017-01-18 21:34
183 查看
一棵树上有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
Sample Output
LCT:
一些操作: 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
LCT:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<string> #include<algorithm> #define F(x) tree[x].fa #define LC(x) tree[x].child[0] #define RC(x) tree[x].child[1] #define REV(x) tree[x].rev #define Size 300010 using namespace std; inline int read(){ int sum=0,fg=1;char c=getchar(); while(c<'0' || c>'9'){if(c=='-')fg=-1;c=getchar();} while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();} return sum*fg; } struct lct{ int fa,child[2],rev; int v,sum,MAX; }tree[Size]; struct link_cut_tree{ inline bool isroot(int x){ return LC(F(x))!=x && RC(F(x))!=x; } inline void pushup(int x){ tree[x].sum=tree[x].MAX=tree[x].v; if(LC(x)){tree[x].sum+=tree[LC(x)].sum;tree[x].MAX=max(tree[x].MAX,tree[LC(x)].MAX);} if(RC(x)){tree[x].sum+=tree[RC(x)].sum;tree[x].MAX=max(tree[x].MAX,tree[RC(x)].MAX);} } inline void pushdown(int x){ if(REV(x)){ REV(x)^=1;REV(LC(x))^=1;REV(RC(x))^=1; swap(LC(x),RC(x)); } } void Pushdown(int x){ if(!isroot(x))Pushdown(F(x)); pushdown(x); } inline void rotate(int x){ int A=F(x),B=F(A);bool w=(RC(A)==x); if(!isroot(A)){ if(LC(B)==A)LC(B)=x; else if(RC(B)==A)RC(B)=x; } F(tree[x].child[w^1])=A;F(A)=x;F(x)=B; tree[A].child[w]=tree[x].child[w^1];tree[x].child[w^1]=A; pushup(A);pushup(x); } inline void splay(int x){ Pushdown(x); while(!isroot(x)){ if(!isroot(F(x)))rotate(x); rotate(x); } } inline void access(int x){ for(int i=0;x;i=x,x=F(x)){splay(x),RC(x)=i,pushup(x);} } inline int find_root(int x){ access(x);splay(x);while(LC(x))x=LC(x); return x; } inline void reverse(int x){ access(x);splay(x);REV(x)^=1; } inline void link(int x,int y){ reverse(x);F(x)=y; } inline void update(int x,int val){ tree[x].sum=tree[x].MAX=tree[x].v=val; splay(x);pushup(x); } inline int query_max(int x,int y){ reverse(x);access(y);splay(y); return tree[y].MAX; } inline int query_sum(int x,int y){ reverse(x);access(y);splay(y); return tree[y].sum; } }LCT; int main(){ int n=read(); for(int i=1;i<n;i++){ int x=read(),y=read(); LCT.link(x,y); } for(int i=1;i<=n;i++){ int val=read(); LCT.update(i,val); } int m=read(); while(m--){ static char tp[10]; scanf("%s",tp); if(tp[0]=='C'){ int x=read(),val=read(); LCT.update(x,val); } else if(tp[1]=='M'){ int x=read(),y=read(); printf("%d\n",LCT.query_max(x,y)); } else{ int x=read(),y=read(); printf("%d\n",LCT.query_sum(x,y)); } } return 0; }
相关文章推荐
- 4种常见的POST数据提交方式
- js - 类模拟
- javascript中的类型转换,宽松相等于严格相等
- 几个命令轻松搞定linux的服务状态
- android Recycle view 放置在能够滑动的view(scrollerview等)自动上划显示的问题
- Java web项目 在线网络考试添加考套题部分代码
- 线段树 A Simple Problem with Integers
- mentohust配置
- MongoDB_Java连接mongo 检索文档中指定字段的不同值
- 购物车点击管理删除和商品价钱的计算
- 输入一个正数,对该数进行四舍五入到个位数的运算。例如,实数12.56经过四舍五入运算,得到结果13;而12.46经过四舍五入运算,得到结果12。
- 02 Sruts详解
- 使用Struts2的输入校验(三)--短路校验器
- Dash:程序员的的好帮手
- 1048 阶乘表
- mysql中文乱码
- 抢答器
- Unity项目脚本编码格式转换为UTF8编码格式
- 01 SSH简介
- 线性规划与网络流24——最小路径覆盖问题