1984: 月下“毛景树”
Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1667 Solved: 514
[ Submit][ Status][ Discuss]
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个。
HINT
Source
//bzoj 1984
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 200003
using namespace std;
int tr[N*4],n,m,cover[N*4],delta[N*4],pos[N],a[N],deep[N],tot,sz,num[N],q[N];
int point[N],next[N],v[N],c[N],val[N],belong[N],size[N],son[N],fa[N],ba[N];
void add(int x,int y,int z,int i)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z; num[tot]=i;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=z; num[tot]=i;
}
void dfs(int x,int f)
{
fa[x]=f; size[x]=1; deep[x]=deep[f]+1;
for (int i=point[x];i;i=next[i])
if (v[i]!=f) {
dfs(v[i],x); val[v[i]]=c[i]; ba[num[i]]=v[i];
size[x]+=size[v[i]];
if (size[son[x]]<size[v[i]]) son[x]=v[i];
}
}
void dfs1(int x,int chain)
{
belong[x]=chain; pos[x]=++sz; q[sz]=x;
if (!son[x]) return;
dfs1(son[x],chain);
for (int i=point[x];i;i=next[i])
if (v[i]!=son[x]&&v[i]!=fa[x])
dfs1(v[i],v[i]);
}
void update(int now)
{
tr[now]=max(tr[now<<1],tr[now<<1|1]);
}
void pushdown(int now)
{
if (cover[now]!=-1) {
tr[now<<1]=cover[now]; tr[now<<1|1]=cover[now];
cover[now<<1]=cover[now<<1|1]=cover[now];
cover[now]=-1; delta[now<<1]=delta[now<<1|1]=0;
}
if (delta[now]) {
tr[now<<1]+=delta[now]; tr[now<<1|1]+=delta[now];
if (cover[now<<1]==-1) delta[now<<1]+=delta[now];
else cover[now<<1]+=delta[now];
if (cover[now<<1|1]==-1) delta[now<<1|1]+=delta[now];
else cover[now<<1|1]+=delta[now];
delta[now]=0;
}
}
void build(int now,int l,int r)
{
if (l==r) {
tr[now]=val[q[l]];
return;
}
int mid=(l+r)/2;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
update(now);
}
void pointchange(int now,int l,int r,int x,int v)
{
if (l==r) {
tr[now]=v;
return;
}
int mid=(l+r)/2;
pushdown(now);
if (x<=mid) pointchange(now<<1,l,mid,x,v);
else pointchange(now<<1|1,mid+1,r,x,v);
update(now);
}
void qjchange(int now,int l,int r,int ll,int rr,int v)
{
if (ll<=l&&r<=rr) {
tr[now]+=v;
if (cover[now]!=-1) cover[now]+=v;
else delta[now]+=v;
return;
}
int mid=(l+r)/2;
pushdown(now);
if (ll<=mid) qjchange(now<<1,l,mid,ll,rr,v);
if (rr>mid) qjchange(now<<1|1,mid+1,r,ll,rr,v);
update(now);
}
void qjcover(int now,int l,int r,int ll,int rr,int v)
{
if (ll<=l&&r<=rr) {
tr[now]=v;
delta[now]=0;
cover[now]=v;
return;
}
int mid=(l+r)/2;
pushdown(now);
if (ll<=mid) qjcover(now<<1,l,mid,ll,rr,v);
if (rr>mid) qjcover(now<<1|1,mid+1,r,ll,rr,v);
update(now);
}
int qjmax(int now,int l,int r,int ll,int rr)
{
if (ll<=l&&r<=rr) return tr[now];
int mid=(l+r)/2;
pushdown(now);
int ans=0;
if (ll<=mid) ans=max(ans,qjmax(now<<1,l,mid,ll,rr));
if (rr>mid) ans=max(ans,qjmax(now<<1|1,mid+1,r,ll,rr));
return ans;
}
void solve(int x,int y,int v,int opt)
{
while (belong[x]!=belong[y]) {
if (deep[belong[x]]<deep[belong[y]]) swap(x,y);
if (!opt) qjchange(1,1,n,pos[belong[x]],pos[x],v);
else qjcover(1,1,n,pos[belong[x]],pos[x],v);
x=fa[belong[x]];
}
if (x==y) return ;
if (deep[x]>deep[y]) swap(x,y);
if (!opt) qjchange(1,1,n,pos[x]+1,pos[y],v);
else qjcover(1,1,n,pos[x]+1,pos[y],v);
}
int solve1(int x,int y)
{
int ans=0;
while (belong[x]!=belong[y]){
if (deep[belong[x]]<deep[belong[y]]) swap(x,y);
ans=max(ans,qjmax(1,1,n,pos[belong[x]],pos[x]));
x=fa[belong[x]];
}
if (deep[x]>deep[y]) swap(x,y);
if (x==y) return ans;
ans=max(ans,qjmax(1,1,n,pos[x]+1,pos[y]));
return ans;
}
int main()
{
freopen("ok.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<n;i++) {
int x,y,z; scanf("%d%d%d",&x,&y,&z);
add(x,y,z,i);
}
memset(cover,-1,sizeof(cover));
dfs(1,0);
dfs1(1,1);
//for (int i=1;i<=n;i++) cout<<val[i]<<" "; cout<<endl;
//for (int i=1;i<=n;i++) cout<<q[i]<<" "; cout<<endl;
build(1,1,n);
while(true){
char s[10]; scanf("%s",s+1);
if (s[1]=='S') break;
if (s[1]=='C'&&s[2]=='h') {
int x,y; scanf("%d%d",&x,&y);
pointchange(1,1,n,pos[ba[x]],y);
}
if (s[1]=='C'&&s[2]=='o') {
int x,y,z; scanf("%d%d%d",&x,&y,&z);
solve(x,y,z,1);
}
if (s[1]=='A') {
int x,y,z; scanf("%d%d%d",&x,&y,&z);
solve(x,y,z,0);
}
if (s[1]=='M') {
int x,y; scanf("%d%d",&x,&y);
printf("%d\n",solve1(x,y));
}
}
}