[BZOJ]1984: 月下“毛景树”
题目大意:树上一系列沙茶操作
Max x--y 树上x--y之间边的最大权值
Cover x--y w.树上x--y之前边的权值都变为w
Add x--y w 树上x--y之间边权都加w
Change x w把第x条边权值改为w
题解:树链剖分
权值是边的不是点的,由于树上每个点只有一个爸爸,所以让每个点记录
它到它爸爸这条边的权值,也就是边的权值降到深度大的端点。
然后再注意的就是双标记下传。
Cover操作一个标记,Add操作一个标记..ps:第一遍写到一半发现标记
不能一起下传..有先后的。
在Cover操作时,将Add标记清0,pushdown时,将儿子的Add标记也清0
Add操作时,Cover标记不用清0。
因为区间加一个值然后全部变为另一个值,区间加这个操作没什么用。
ps:修改忘记pushup,WA了...有毒...
代码:差点破200..
#include<iostream> #include<cstdio> #include<cstring> #define maxn 300009 using namespace std; int n,m,cnt,sumedge; int size[maxn],dad[maxn],deep[maxn],top[maxn],head[maxn]; int tpos[maxn],re[maxn],fe[maxn],st[maxn],ed[maxn]; char s[10]; struct Tree{ int l,r,mx,adc,cvs; }tr[maxn<<2]; struct Edge{ int x,y,z,nxt; Edge(int x=0,int y=0,int z=0,int nxt=0): x(x),y(y),z(z),nxt(nxt){} }edge[maxn<<1]; void add(int x,int y,int z){ edge[++sumedge]=Edge(x,y,z,head[x]); head[x]=sumedge; } void dfs(int x){ size[x]=1;deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==dad[x])continue; dad[v]=x;fe[v]=edge[i].z;dfs(v); size[x]+=size[v]; } } void dfs_(int x){ int s=0; if(!top[x])top[x]=x; tpos[x]=++cnt;re[cnt]=x; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&size[v]>size[s])s=v; } if(s){ top[s]=top[x]; dfs_(s); } for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&v!=s)dfs_(v); } } void pushup(int rt){ tr[rt].mx=max(tr[rt<<1].mx,tr[rt<<1|1].mx); return; } void pushdown(int rt){ if(tr[rt].cvs!=-1){ tr[rt<<1].mx=tr[rt<<1|1].mx=tr[rt].cvs; tr[rt<<1].adc=tr[rt<<1|1].adc=0; tr[rt<<1].cvs=tr[rt<<1|1].cvs=tr[rt].cvs; tr[rt].cvs=-1; } if(tr[rt].adc){ tr[rt<<1].mx+=tr[rt].adc;tr[rt<<1|1].mx+=tr[rt].adc; tr[rt<<1].adc+=tr[rt].adc;tr[rt<<1|1].adc+=tr[rt].adc; tr[rt].adc=0; } } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r;tr[rt].cvs=-1; if(l==r){ tr[rt].mx=fe[re[l]]; return; } int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); pushup(rt); } //----------------------------------------------------- void change_Node(int rt,int l,int r,int p,int w){ if(l==r){ tr[rt].mx=w; return; } pushdown(rt); int mid=(l+r)>>1; if(p<=mid)change_Node(rt<<1,l,mid,p,w); if(p>mid)change_Node(rt<<1|1,mid+1,r,p,w); pushup(rt); } void change_node(int k,int w){ int p,x,y; x=st[k];y=ed[k];p=dad[x]==y?x:y; change_Node(1,1,n,tpos[p],w); } //-------------------------------------------------------- void change_Cover(int rt,int l,int r,int ql,int qr,int w){ if(l>=ql&&r<=qr){ tr[rt].mx=w;tr[rt].cvs=w;tr[rt].adc=0; return; } pushdown(rt); int mid=(l+r)>>1; if(ql<=mid)change_Cover(rt<<1,l,mid,ql,qr,w); if(qr>mid)change_Cover(rt<<1|1,mid+1,r,ql,qr,w); pushup(rt); } void change_cover(int x,int y,int w){ for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); change_Cover(1,1,n,tpos[top[y]],tpos[y],w); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); change_Cover(1,1,n,tpos[x]+1,tpos[y],w); } //--------------------------------------------------------- void change_Add(int rt,int l,int r,int ql,int qr,int w){ if(l>=ql&&r<=qr){ tr[rt].mx+=w;tr[rt].adc+=w; return; } pushdown(rt); int mid=(l+r)>>1; if(ql<=mid)change_Add(rt<<1,l,mid,ql,qr,w); if(qr>mid)change_Add(rt<<1|1,mid+1,r,ql,qr,w); pushup(rt); } void change_add(int x,int y,int w){ for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); change_Add(1,1,n,tpos[top[y]],tpos[y],w); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); change_Add(1,1,n,tpos[x]+1,tpos[y],w); } //----------------------------------------------------------- int query_mx(int rt,int l,int r,int ql,int qr){ if(l>=ql&&r<=qr){ return tr[rt].mx; } pushdown(rt); int mid=(l+r)>>1,ret=-1; if(ql<=mid)ret=max(ret,query_mx(rt<<1,l,mid,ql,qr)); if(qr>mid)ret=max(ret,query_mx(rt<<1|1,mid+1,r,ql,qr)); return ret; } int query(int x,int y){ int ans=-1; for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); ans=max(ans,query_mx(1,1,n,tpos[top[y]],tpos[y])); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); ans=max(ans,query_mx(1,1,n,tpos[x]+1,tpos[y])); return ans; } //------------------------------------------------------------ int main(){ scanf("%d",&n); for(int i=1;i<n;i++){ int z; scanf("%d%d%d",&st[i],&ed[i],&z); add(st[i],ed[i],z);add(ed[i],st[i],z); } dfs(1);dfs_(1);build(1,1,n); while(1){ int x,y,z; scanf("%s",s); if(s[0]=='S')break; if(s[1]=='h'){ scanf("%d%d",&x,&z); change_node(x,z); }else if(s[1]=='o'){ scanf("%d%d%d",&x,&y,&z); change_cover(x,y,z); }else if(s[1]=='d'){ scanf("%d%d%d",&x,&y,&z); change_add(x,y,z); }else if(s[2]=='x'){ scanf("%d%d",&x,&y); printf("%d\n",query(x,y)); } } return 0; }