Description
毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~ 毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数: Change k w:将第k条树枝上毛毛果的个数改变为w个。 Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。 Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问: Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
Input
第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。
Output
对于毛毛虫的每个询问操作,输出一个答案。
Sample Input
4
1 2 8
1 3 7
3 4 9
Max 2 4
Cover 2 4 5
Add 1 4 10
Change 1 16
Max 2 4
Stop
Sample Output
9
16
【Data Range】
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。
HINT
Source
树的分治
bzoj不让我交!!!
我和【submit】这个键战斗了无数次!!
然后每次都【无法显示该网页】!!
挖坑!!!
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int SZ = 400010;
const int INF = 1000000010;
int head[SZ],nxt[SZ],tot = 0,to[SZ];
void build_edge(int f,int t)
{
to[++ tot] = t;
nxt[tot] = head[f];
head[f] = tot;
}
int top[SZ],deep[SZ],sz[SZ],son[SZ],fa[SZ],inseg[SZ];
void dfs_1(int u,int f)
{
fa[u] = f;
sz[u] = 1;
deep[u] = deep[f] + 1;
for(int i = head[u];i;i = nxt[i])
{
int v = to[i];
if(v == f) continue;
dfs_1(v,u);
sz[u] += sz[v];
if(!son[u] || sz[son[u]] < sz[v]) son[u] = v;
}
}
int totp = 0;
void dfs_2(int u,int tp)
{
inseg[u] = ++ totp;
top[u] = tp;
if(!son[u]) return;
dfs_2(son[u],tp);
for(int i = head[u];i;i = nxt[i])
{
int v = to[i];
if(v == fa[u] || v == son[u]) continue;
dfs_2(v,v);
}
}
struct segment{
int l,r;
int add,maxn,c;
}tree[SZ << 2];
void update(int p)
{
tree[p].maxn = max(tree[p << 1].maxn,tree[p << 1 | 1].maxn);
}
void build_seg(int p,int l,int r)
{
tree[p].l = l; tree[p].r = r;
if(l == r)
{
tree[p].maxn = tree[p].add = 0;
return;
}
int mid = (l + r) >> 1;
build_seg(p << 1,l,mid);
build_seg(p << 1 | 1,mid + 1,r);
update(p);
}
void spread(int p)
{
if(tree[p].c)
{
tree[p << 1].c = tree[p << 1 | 1].c = tree[p].c;
tree[p << 1].maxn = tree[p << 1 | 1].maxn = tree[p].c;
tree[p << 1].add = tree[p << 1 | 1].add = 0;
tree[p].c = 0;
}
if(tree[p].add)
{
tree[p << 1].maxn += tree[p].add; tree[p << 1 | 1].maxn += tree[p].add;
if(tree[p << 1].c) tree[p << 1].c += tree[p].add;
else tree[p << 1].add += tree[p].add;
if(tree[p << 1 | 1].c) tree[p << 1 | 1].c += tree[p].add;
else tree[p << 1 | 1].add += tree[p].add;
tree[p].add = 0;
}
}
void change(int p,int l,int r,int d)
{
if(l <= tree[p].l && tree[p].r <= r)
{
tree[p].add = 0;
tree[p].c = tree[p].maxn = d;
return;
}
spread(p);
int mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) change(p << 1,l,r,d);
if(mid < r) change(p << 1 | 1,l,r,d);
update(p);
}
void add(int p,int l,int r,int d)
{
if(l <= tree[p].l && tree[p].r <= r)
{
if(tree[p].c) tree[p].c += d;
else tree[p].add += d;
tree[p].maxn += d;
return;
}
spread(p);
int mid = (tree[p].l + tree[p].r) >> 1;
if(l <= mid) add(p << 1,l,r,d);
if(mid < r) add(p << 1 | 1,l,r,d);
update(p);
}
int ask(int p,int l,int r)
{
if(l <= tree[p].l && tree[p].r <= r)
return tree[p].maxn;
spread(p);
int mid = (tree[p].l + tree[p].r) >> 1;
int ans = 0;
if(l <= mid) ans = max(ans,ask(p << 1,l,r));
if(mid < r) ans = max(ans,ask(p << 1 | 1,l,r));
return ans;
}
void find_change(int x,int y,int d)
{
int fx = top[x],fy = top[y];
while(fx != fy)
{
if(deep[fx] < deep[fy]) swap(x,y),swap(fx,fy);
change(1,inseg[fx],inseg[x],d);
x = fa[fx]; fx = top[x];
}
if(x != y)
{
if(deep[x] > deep[y]) swap(x,y);
change(1,inseg[x] + 1,inseg[y],d);
}
}
void find_add(int x,int y,int d)
{
int fx = top[x],fy = top[y];
while(fx != fy)
{
if(deep[fx] < deep[fy]) swap(x,y),swap(fx,fy);
add(1,inseg[fx],inseg[x],d);
x = fa[fx]; fx = top[x];
}
if(x != y)
{
if(deep[x] > deep[y]) swap(x,y);
add(1,inseg[x] + 1,inseg[y],d);
}
}
int find_ans(int x,int y)
{
int fx = top[x],fy = top[y];
int ans = 0;
while(fx != fy)
{
if(deep[fx] < deep[fy]) swap(x,y),swap(fx,fy);
ans = max(ans,ask(1,inseg[fx],inseg[x]));
x = fa[fx]; fx = top[x];
}
if(x != y)
{
if(deep[x] > deep[y]) swap(x,y);
ans = max(ans,ask(1,inseg[x] + 1,inseg[y]));
}
return ans;
}
struct edge{
int f,t,d;
}l[SZ];
int main()
{
int n;
scanf("%d",&n);
for(int i = 1;i < n;i ++)
{
scanf("%d%d%d",&l[i].f,&l[i].t,&l[i].d);
build_edge(l[i].f,l[i].t);
build_edge(l[i].t,l[i].f);
}
dfs_1(1,0); dfs_2(1,1);
build_seg(1,1,n);
for(int i = 1;i < n;i ++)
{
if(deep[l[i].f] > deep[l[i].t]) swap(l[i].f,l[i].t);
change(1,inseg[l[i].t],inseg[l[i].t],l[i].d);
}
char opt[10];
while(~scanf("%s",opt) && opt[1] != 't')
{
if(opt[1] == 'h')
{
int k,w;
scanf("%d%d",&k,&w);
change(1,inseg[l[k].t],inseg[l[k].t],w);
}
else if(opt[1] == 'o')
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
find_change(u,v,w);
}
else if(opt[1] == 'd')
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
find_add(u,v,w);
}
else if(opt[1] == 'a')
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",find_ans(u,v));
}
// for(int i = 1;i <= n;i ++) printf("%d ",find_ans(i,i)); puts("");
}
return 0;
}