BZOJ 1984 月下“毛景树”
2018.03.03
2018.03.03
不得不吐槽一下……这题太蛇皮了……(或许是我太久没写线段树相关结果无论是今天比赛还是这道题被线段树虐到死去活来,被水淹没,不知所措……
给你一棵边权树,请你维护它,支持:统一更改路径上权值,更改某条边权值,统一增大路径上权值,求路径上最大边权值。
这道题不知道debug了多长时间了……
线段树基本知识:
还有树剖的知识:
大概就是这样。调了好久才调出来啊……GG
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson pos<<1
#define rson pos<<1|1
#define maxN 200010
int n,m,top[maxN],head[maxN<<1],nex[maxN<<1],to[maxN<<1],tot,inx,iny,inz,u[maxN],v[maxN],siz[maxN],cnt,depth[maxN],lazchg[maxN<<2],lazup[maxN<<2];
int num[maxN],fa[maxN],son[maxN],val[maxN<<2],initval[maxN],inittmp[maxN];
char mode[maxN];
void addedge(int tx,int ty,int tz) {to[++tot]=ty,nex[tot]=head[tx],head[tx]=tot,val[tot]=tz;}
void dfs1(int pos,int pre)
{
depth[pos]=depth[pre]+1;
siz[pos]=1;
fa[pos]=pre;
for(int i=head[pos];i;i=nex[i])
if(to[i]!=pre)
{
initval[to[i]]=val[i];
dfs1(to[i],pos);
siz[pos]+=siz[to[i]];
if(siz[son[pos]]<siz[to[i]]) son[pos]=to[i];
}
return;
}
void dfs2(int pos,int pre)
{
num[pos]=++cnt;
top[pos]=pre;
inittmp[num[pos]]=initval[pos];
if(son[pos]) dfs2(son[pos],pre);
for(int i=head[pos];i;i=nex[i])
if(to[i]!=fa[pos]&&to[i]!=son[pos])
dfs2(to[i],to[i]);
return;
}
void pushup(int pos){val[pos]=max(val[lson],val[rson]);}
void build(int pos,int l,int r)
{
if(l==r)
{
val[pos]=inittmp[l];
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(pos);
return;
}
void pushdown(int pos)
{
if(lazup[pos])
{
if(lazchg[lson]!=-1) lazchg[lson]+=lazup[pos];
else lazup[lson]+=lazup[pos];
if(lazchg[rson]!=-1) lazchg[rson]+=lazup[pos];
else lazup[rson]+=lazup[pos];
val[lson]+=lazup[pos];
val[rson]+=lazup[pos];
lazup[pos]=0;
}
if(lazchg[pos]!=-1)
{
lazup[lson]=lazup[rson]=0;
lazchg[lson]=lazchg[rson]=lazchg[pos];
val[lson]=val[rson]=lazchg[pos];
lazchg[pos]=-1;
lazup[pos]=lazup[lson]=lazup[rson]=0;
}
}
void change(int pos,int l,int r,int x,int y)
{
pushdown(pos);
if(x==l&&x==r)
{
val[pos]=y;
return;
}
int mid=(l+r)>>1;
if(x<=mid) change(lson,l,mid,x,y);
else change(rson,mid+1,r,x,y);
pushup(pos);
}
void addq(int pos,int l,int r,int x,int y,int tg)
{
pushdown(pos);
if(x<=l&&r<=y)
{
lazup[pos]+=tg;
val[pos]+=tg;
return;
}
int mid=(l+r)>>1;
if(x<=mid) addq(lson,l,mid,x,y,tg);
if(y>mid) addq(rson,mid+1,r,x,y,tg);
pushup(pos);
}
void add(int tx,int ty,int tz)
{
while(top[tx]!=top[ty])
{
if(depth[top[tx]]<depth[top[ty]]) swap(tx,ty);
addq(1,1,n,num[top[tx]],num[tx],tz);
tx=fa[top[tx]];
}
if(depth[tx]>depth[ty]) swap(tx,ty);
if(tx!=ty) addq(1,1,n,num[tx]+1,num[ty],tz);
}
int query(int pos,int l,int r,int x,int y)
{
pushdown(pos);
if(x<=l&&r<=y) return val[pos];
int mid=(l+r)>>1,ret=0;
if(x<=mid) ret=max(ret,query(lson,l,mid,x,y));
if(y>mid) ret=max(ret,query(rson,mid+1,r,x,y));
return ret;
}
int qmax(int tx,int ty)
{
int ret=0;
while(top[tx]!=top[ty])
{
if(depth[top[tx]]<depth[top[ty]]) swap(tx,ty);
ret=max(ret,query(1,1,n,num[top[tx]],num[tx]));
tx=fa[top[tx]];
}
if(depth[tx]>depth[ty]) swap(tx,ty);
if(tx!=ty) ret=max(ret,query(1,1,n,num[tx]+1,num[ty]));
return ret;
}
void cov(int pos,int l,int r,int x,int y,int z)
{
pushdown(pos);
if(x<=l&&r<=y) {val[pos]=z;lazchg[pos]=z;return;}
int mid=(l+r)>>1;
if(x<=mid) cov(lson,l,mid,x,y,z);
if(y>mid) cov(rson,mid+1,r,x,y,z);
pushup(pos);
}
void cover(int tx,int ty,int tz)
{
while(top[tx]!=top[ty])
{
if(depth[top[tx]]<depth[top[ty]]) swap(tx,ty);
cov(1,1,n,num[top[tx]],num[tx],tz);
tx=fa[top[tx]];
}
if(depth[tx]>depth[ty]) swap(tx,ty);
if(tx!=ty) cov(1,1,n,num[tx]+1,num[ty],tz);
}
int main()
{
scanf("%d",&n);
memset(lazchg,-1,sizeof lazchg);
for(int i=1;i<n;++i) scanf("%d%d%d",u+i,v+i,&inx),addedge(u[i],v[i],inx),addedge(v[i],u[i],inx);
dfs1(1,0);
cnt=0;
dfs2(1,1);
build(1,1,n);
while(true)
{
scanf("%s",mode);
switch(mode[1])
{
case 'h'://Change
{
scanf("%d%d",&inx,&iny);
if(depth[u[inx]]<depth[v[inx]]) swap(u[inx],v[inx]);
change(1,1,n,num[u[inx]],iny);
break;
}
case 'o'://Cover
{
scanf("%d%d%d",&inx,&iny,&inz);
cover(inx,iny,inz);
break;
}
case 'd'://Add
{
scanf("%d%d%d",&inx,&iny,&inz);
add(inx,iny,inz);
break;
}
case 'a'://Max
{
scanf("%d%d",&inx,&iny);
printf("%d\n",qmax(inx,iny));
break;
}
case 't':return 0;//Stop
}
}
}