SPOJ-GSS7 Can you answer these queries VII(树上区间最大和)
来源:互联网 发布:linux 双网卡双网关 编辑:程序博客网 时间:2024/06/07 05:36
Given a tree with N (N <= 100000) nodes. Each node has a interger value x_i (|x_i|<= 10000).
You have to apply Q (Q <= 100000) operations:
1. 1 a b : answer the maximum contiguous sum (maybe empty,will always larger than or equal to 0 ) from the path a->b ( inclusive ).
2. 2 a b c : change all value in the path a->b ( inclusive ) to c. (|c| <= 10000)
Input
first line consists one interger N.
next line consists N interger x_i.
next N-1 line , each consists two interger u,v , means that node u and node v are connected
next line consists 1 interger Q.
next Q line : 1 a b or 2 a b c .
Output
For each query, output one line the maximum contiguous sum.
Example
Input:5-3 -2 1 2 31 22 31 44 531 2 52 3 4 21 2 5Output:59
题意:给一点权棵树,有两个操作,修改和查询,每次修改u 到 v路径上所有的点权,每次查询u 到 v路径上的最大连续区间和。
分析:类似线段树的做法,每次push_up时分类讨论一下就可以了。
#include <cstdio>#include <iostream>#include <vector>#include <algorithm>#include <cmath>#include <cstring>#define MAXN 100015#define NONE 10001using namespace std;int n,q,op,u,v,c,lc[MAXN],rc[MAXN],ch[MAXN][2],s[MAXN],size[MAXN],sum[MAXN],maxsum[MAXN],value[MAXN],fa[MAXN],lazy2[MAXN];bool lazy[MAXN];inline bool isroot(int x){return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}void push_up(int x){lc[0] = rc[0] = maxsum[0] = sum[0] = size[0] = 0;size[x] = size[ch[x][0]] + 1 + size[ch[x][1]];sum[x] = sum[ch[x][0]] + value[x] + sum[ch[x][1]];maxsum[x] = max(maxsum[ch[x][0]],maxsum[ch[x][1]]);maxsum[x] = max(maxsum[x],rc[ch[x][0]] + value[x] + lc[ch[x][1]]);lc[x] = max(lc[ch[x][0]],sum[ch[x][0]] + value[x] + lc[ch[x][1]]);rc[x] = max(rc[ch[x][1]],sum[ch[x][1]] + value[x] + rc[ch[x][0]]);}void rotate(int x){int y = fa[x],z = fa[y];int d = ch[y][0] == x ? 0 : 1;if(!isroot(y)){if(ch[z][0] == y) ch[z][0] = x;else ch[z][1] = x;}fa[y] = x,fa[x] = z,fa[ch[x][d^1]] = y;ch[y][d] = ch[x][d^1],ch[x][d^1] = y;push_up(y),push_up(x);}void change(int x,int y){lazy2[x] = value[x] = y;maxsum[x] = rc[x] = lc[x] = y > 0 ? size[x]*y : 0;sum[x] = size[x]*y;}inline void push_down(int x){if(lazy[x]){int ls = ch[x][0],rs = ch[x][1];lazy[x]^=1,lazy[ls]^=1;lazy[rs]^=1;swap(ch[ls][0],ch[ls][1]);swap(ch[rs][0],ch[rs][1]);swap(lc[ls],rc[ls]);swap(lc[rs],rc[rs]);}if(lazy2[x] != NONE){change(ch[x][0],lazy2[x]),change(ch[x][1],lazy2[x]);lazy2[x] = NONE;}}void splay(int x){int tot = 0;s[++tot] = x;for(int i = x;!isroot(i);i = fa[i]) s[++tot] = fa[i];for(;tot;tot--) push_down(s[tot]);while(!isroot(x)){int y = fa[x],z = fa[y];if(!isroot(y)){if((ch[z][0] == y) ^ (ch[y][0] == x)) rotate(x);else rotate(y);}rotate(x);}}void access(int x){int t = 0;while(x){splay(x);ch[x][1] = t; //parent path 边中儿子一定是子链root,父亲是子链root实际父亲 push_up(x);t = x,x = fa[x];}}void makeroot(int x) //x变成根 {access(x),splay(x);swap(ch[x][0],ch[x][1]);lazy[x]^=1; }void link(int x,int y){makeroot(x);fa[x] = y;}int main(){scanf("%d",&n);for(int i = 1;i <= n;i++) {scanf("%d",&value[i]);maxsum[i] = lc[i] = rc[i] = max(0,value[i]); size[i] = 1,sum[i] = value[i];lazy2[i] = NONE;}for(int i = 1;i < n;i++){scanf("%d%d",&u,&v);link(u,v);}scanf("%d",&q);for(int i = 1;i <= q;i++){scanf("%d",&op);if(op == 1){scanf("%d%d",&u,&v);makeroot(u);access(v);splay(v);printf("%d\n",maxsum[v]);}else{scanf("%d%d%d",&u,&v,&c);makeroot(u);access(v);splay(v);change(v,c);}}}
- SPOJ-GSS7 Can you answer these queries VII(树上区间最大和)
- SPOJ GSS7 Can you answer these queries VII
- SPOJ GSS7 Can you answer these queries VII(LCT)
- Spoj 6779 Can you answer these queries VII 树链剖分 在树上任意路径的最大子段和 区间修改点权
- 【SPOJ】6779 Can you answer these queries VII 树链剖分+线段树 求树上的最大子段和
- spoj6779 Can you answer these queries VII(gss7)动态树
- SPOJ GSS1 Can you answer these queries I (线段树求区间最大连续和)
- spoj 6779. Can you answer these queries VII(树链剖分)
- SPOJ 6779 Can you answer these queries VII 树链剖分
- SPOJGSS7 Can you answer these queries VII
- SPOJ 1043 Can you answer these queries I 求任意区间最大连续子段和 线段树
- Spoj 1557 Can you answer these queries II 线段树 任意区间最大子段和 不重复数字
- Spoj 1716 Can you answer these queries III 线段树 单点修改 区间求最大子段和
- Spoj 2916 Can you answer these queries V 线段树 求任意重叠区间的最大子段和
- Splay树(插入、删除、区间最大字段和)—— SPOJ - GSS6 Can you answer these queries VI
- SPOJ Can you answer these queries V
- spoj(GSS3) 1716 Can you answer these queries III(线段树求最大子段和)
- 【SPOJ-GSS1】Can you answer these queries I【线段树】【最大子段和】
- [K大子串 后缀自动机 模板题] BZOJ 3998 [TJOI2015]弦论
- Java 1.8 新特性之(Lambda表达式)
- 创建二叉树,并先序遍历
- 【IMX6UL开发板试用体验】OpenWRT有线网络的配置
- c++判断文件编码格式
- SPOJ-GSS7 Can you answer these queries VII(树上区间最大和)
- AsyncTask的源码分析,非常详细!
- Servlet之ServletContext创建对象和作用
- 12c Oracle_Home下的监听器监听11g数据库的问题
- [后缀自动机] POJ 1743 Musical Theme
- Android之旅第四站——Simpleapter的使用…
- 破坏性批评与建设性批评
- [后缀自动机 parent树] BZOJ 4566 [Haoi2016]找相同字符
- 艳辉网V2.0之采集系统