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 3 1 2 2 3 1 4 4 5 3 1 2 5 2 3 4 2 1 2 5 Output: 59
题意:给一点权棵树,有两个操作,修改和查询,每次修改u 到 v路径上所有的点权,每次查询u 到 v路径上的最大连续区间和。
分析:类似线段树的做法,每次push_up时分类讨论一下就可以了。
#include <cstdio> #include <iostream> #include <vector> #include <algorithm> #include <cmath> #include <cstring> #define MAXN 100015 #define NONE 10001 using 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); } } }