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
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个。
16
【Data Range】
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。
检查了一个下午...结果竟然是存边的数组大小忘了翻倍了...给跪
这题是树链剖分..区间加和区间覆盖。维护点权变成了维护边权,我们可以把边权存成这条边到达的节点的点权,然后就和做点权的树链剖分一样了。最后两点在一条链的时候上面那个点的点权不需要加入ans。
【依旧是写了300多行的树链剖分】
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct line
{
int s,t,x;
int next;
}a[200001];
int edge;
int head[100001];
inline void add(int s,int t,int x)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
a[edge].x=x;
}
struct tree
{
int l,r;
int max;
int tag1,tag2;//1cover 2add
}tr[800001];
inline int max(int x,int y)
{
if(x>y)
return x;
return y;
}
inline void up(int p)
{
tr[p].max=max(tr[p*2].max,tr[p*2+1].max);
//tr[p].s=tr[p*2].s+tr[p*2+1].s;
}
inline void down(int p)
{
if(tr[p].tag1!=0)
{
tr[p*2].max=tr[p].tag1;
tr[p*2+1].max=tr[p].tag1;
tr[p*2].tag1=tr[p].tag1;
tr[p*2+1].tag1=tr[p].tag1;
tr[p*2].tag2=0;
tr[p*2+1].tag2=0;
tr[p].tag1=0;
tr[p].tag2=0;
}
else if(tr[p].tag2!=0)
{
if(tr[p*2].tag1!=0&&tr[p*2].l!=tr[p*2].r)
down(p*2);
if(tr[p*2+1].tag1!=0&&tr[p*2+1].l!=tr[p*2+1].r)
down(p*2+1);
tr[p*2].max+=tr[p].tag2;
tr[p*2+1].max+=tr[p].tag2;
tr[p*2].tag2+=tr[p].tag2;
tr[p*2+1].tag2+=tr[p].tag2;
tr[p].tag2=0;
}
}
inline void build(int p,int l,int r)
{
tr[p].l=l;
tr[p].r=r;
tr[p].max=-21000000;
if(l!=r)
{
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
}
}
inline void change(int p,int l,int r,int x)
{
if(l<=tr[p].l&&tr[p].r<=r)
{
down(p);
if(tr[p].max!=-21000000)
tr[p].max+=x;
else
tr[p].max=x;
tr[p].tag2+=x;
}
else
{
down(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
change(p*2,l,r,x);
if(r>mid)
change(p*2+1,l,r,x);
up(p);
}
}
inline void cover(int p,int l,int r,int x)
{
if(l<=tr[p].l&&tr[p].r<=r)
{
// down(p);
tr[p].max=x;
tr[p].tag1=x;
tr[p].tag2=0;
}
else
{
down(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
cover(p*2,l,r,x);
if(r>mid)
cover(p*2+1,l,r,x);
up(p);
}
}
inline int find(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r)
return tr[p].max;
else
{
down(p);
int mid=(tr[p].l+tr[p].r)/2;
int ans=-21000000;
if(l<=mid)
ans=max(ans,find(p*2,l,r));
if(r>mid)
ans=max(ans,find(p*2+1,l,r));
up(p);
return ans;
}
}
int dep[100001],size[100001],son[100001],fa[100001];
int top[100001],w[100001];
bool fx[200001];
int lson[100001]/*最大节点位置*/,mson[100001]/*最大节点值*/;
int tot;
int s;
bool vis[100001];
inline void dfs1(int d)
{
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t!=fa[d]&&!vis[t])
{
// printf("%d\n",t);
vis[t]=true;
dep[t]=dep[d]+1;
fa[t]=d;
dfs1(t);
son[d]+=son[t]+1;
if(son[t]>=mson[d])
{
mson[d]=son[t];
lson[d]=t;
}
}
}
}
inline void dfs2(int d)
{
s++;
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t==lson[d])
{
top[t]=top[d];
tot++;
w[t]=tot;
fx[i]=true;
dfs2(t);
}
}
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t!=fa[d]&&t!=lson[d])
{
top[t]=t;
tot++;
w[t]=tot;
fx[i]=true;
dfs2(t);
}
}
}
tree xx;
inline int ask(int s,int t)
{
int u=top[s],v=top[t];
int ans;
ans=-21000000;
while(u!=v)
{
if(dep[u]>dep[v])
{
ans=max(ans,find(1,w[u],w[s]));
s=fa[top[s]];
}
else
{
ans=max(ans,find(1,w[v],w[t]));
t=fa[top[t]];
}
u=top[s];
v=top[t];
}
if(w[s]<w[t])
ans=max(ans,find(1,w[s]+1,w[t]));
else if(w[s]>w[t])
ans=max(ans,find(1,w[t]+1,w[s]));
return ans;
}
inline void addx(int s,int t,int xx)
{
int u=top[s],v=top[t];
int ans;
ans=-21000000;
while(u!=v)
{
if(dep[u]>dep[v])
{
change(1,w[u],w[s],xx);
s=fa[top[s]];
}
else
{
change(1,w[v],w[t],xx);
t=fa[top[t]];
}
u=top[s];
v=top[t];
}
if(w[s]<w[t])
change(1,w[s]+1,w[t],xx);
else if(w[s]>w[t])
change(1,w[t]+1,w[s],xx);
}
inline void cov(int s,int t,int xx)
{
int u=top[s],v=top[t];
int ans;
ans=-21000000;
while(u!=v)
{
if(dep[u]>dep[v])
{
cover(1,w[u],w[s],xx);
s=fa[top[s]];
}
else
{
cover(1,w[v],w[t],xx);
t=fa[top[t]];
}
u=top[s];
v=top[t];
}
if(w[s]<w[t])
cover(1,w[s]+1,w[t],xx);
else if(w[s]>w[t])
cover(1,w[t]+1,w[s],xx);
}
struct save
{
int s,t,x;
}b[100001];
int main()
{
// freopen("msn.in","r",stdin);
// freopen("msn.out","w",stdout);
int n;
scanf("%d",&n);
int i,s,t,xx;
for(i=1;i<=n-1;i++)
{
scanf("%d%d%d",&b[i].s,&b[i].t,&b[i].x);
edge++;
add(b[i].s,b[i].t,b[i].x);
edge++;
add(b[i].t,b[i].s,b[i].x);
}
dep[1]=1;
s=0;
vis[1]=true;
dfs1(1);
top[1]=1;
tot++;
w[1]=tot;
s=0;
dfs2(1);
build(1,1,n);
for(i=1;i<=edge;i++)
{
if(fx[i])
{
int t=a[i].t;
change(1,w[t],w[t],a[i].x);
}
}
char x[101];
// string x;
int sumx=0;
while(1)
{
//scanf("%s",&x);
/* cin>>x;
int flag;
if(x[0]=='M')
flag=1;
else if(x[0]=='C')
{
if(x[1]=='o')
flag=2;
else if(x[1]=='h')
flag=4;
}
else if(x[0]=='A')
flag=3;
else if(x[0]=='S')
break;*/
scanf("%s",&x);
int flag;
if(x[0]=='M')
flag=1;
else if(x[0]=='C')
{
if(x[1]=='o')
flag=2;
else if(x[1]=='h')
flag=4;
}
else if(x[0]=='A')
flag=3;
else if(x[0]=='S')
break;
if(flag==1)
{
scanf("%d%d",&s,&t);
printf("%d\n",ask(s,t));
}
else if(flag==2)
{
scanf("%d%d%d",&s,&t,&xx);
cov(s,t,xx);
}
else if(flag==3)
{
scanf("%d%d%d",&s,&t,&xx);
addx(s,t,xx);
}
else if(flag==4)
{
scanf("%d%d",&s,&xx);
if(fx[s*2-1])
{
t=a[s*2-1].t;
cover(1,w[t],w[t],xx);
}
else if(fx[s*2])
{
t=a[s*2].t;
cover(1,w[t],w[t],xx);
}
}
}
return 0;
}