您的位置:首页 > 产品设计 > UI/UE

SPOJ-GSS7 Can you answer these queries VII(树上区间最大和)

2017-01-28 21:15 597 查看
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:
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 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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐