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:5

9

题意:给一点权棵树,有两个操作,修改和查询,每次修改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);}}}



0 0