BZOJ 1984 月下“毛景树” 树链剖分+线段树
题意
bzoj好像把这题删了,在洛谷里找的
毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。
爬啊爬爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~ “毛景树”上有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之间树枝上毛毛果个数最多有多少个。
分析
把边权转成点权,然后就是树链剖分裸题了,线段树维护下区间最大值就完事了
Code
#include<bits/stdc++.h> #define fi first #define se second #define pb push_back #define lson l,mid,p<<1 #define rson mid+1,r,p<<1|1 using namespace std; typedef long long ll; const int inf=1e9; const int maxn=2e5; int n; int a[maxn],w[maxn],b[maxn]; typedef pair<int,int> pii; vector<pii>g[maxn]; int top[maxn],f[maxn],d[maxn],id[maxn],p[maxn],sz[maxn],son[maxn],tot; int mx[maxn<<2],t1[maxn<<2],t2[maxn<<2],t3[maxn<<2]; void pp(int p){mx[p]=max(mx[p<<1],mx[p<<1|1]);} void bd(int l,int r,int p){ t1[p]=-1; if(l==r) return mx[p]=a[id[l]],void(); int mid=l+r>>1; bd(lson);bd(rson);pp(p); } void pd(int p,int a,int b){ if(a!=-1){ mx[p]=a;t1[p]=a;t2[p]=0; }mx[p]+=b;t2[p]+=b; } void up(int dl,int dr,int l,int r,int p,int k,int op){ if(l>=dl&&r<=dr){ if(op==1){ mx[p]=k;t1[p]=k; t2[p]=0; }else{ mx[p]+=k;t2[p]+=k; } return; }int mid=l+r>>1; pd(p<<1,t1[p],t2[p]);pd(p<<1|1,t1[p],t2[p]);t1[p]=-1;t2[p]=0; if(dl<=mid) up(dl,dr,lson,k,op); if(dr>mid) up(dl,dr,rson,k,op); pp(p); } int qy(int dl,int dr,int l,int r,int p){ if(l>=dl&&r<=dr) return mx[p]; int mid=l+r>>1;int ret=-inf; pd(p<<1,t1[p],t2[p]);pd(p<<1|1,t1[p],t2[p]);t1[p]=-1;t2[p]=0; if(dl<=mid) ret=max(ret,qy(dl,dr,lson)); if(dr>mid) ret=max(ret,qy(dl,dr,rson)); return ret; } void dfs1(int u){ sz[u]=1;d[u]=d[f[u]]+1; for(pii x:g[u]){ if(x.fi==f[u]) continue; f[x.fi]=u;dfs1(x.fi); a[x.fi]=w[x.se];b[x.se]=x.fi;sz[u]+=sz[x.fi]; if(sz[x.fi]>sz[son[u]]) son[u]=x.fi; } } void dfs2(int u,int t){ top[u]=t;p[u]=++tot;id[tot]=u; if(son[u]) dfs2(son[u],t); for(pii x:g[u]){ if(x.fi==f[u]||x.fi==son[u]) continue; dfs2(x.fi,x.fi); } } void col(int x,int y,int k,int op){ while(top[x]!=top[y]){ if(d[top[x]]<d[top[y]]) swap(x,y); up(p[top[x]],p[x],1,n,1,k,op); x=f[top[x]]; } if(d[x]<d[y]) swap(x,y); up(p[y]+1,p[x],1,n,1,k,op); } int cal(int x,int y){ int res=-inf; while(top[x]!=top[y]){ if(d[top[x]]<d[top[y]]) swap(x,y); res=max(res,qy(p[top[x]],p[x],1,n,1)); x=f[top[x]]; } if(d[x]<d[y]) swap(x,y); return max(res,qy(p[y]+1,p[x],1,n,1)); } int main(){ scanf("%d",&n); for(int i=1,a,b;i<n;i++){ scanf("%d%d%d",&a,&b,&w[i]); g[a].pb(pii(b,i));g[b].pb(pii(a,i)); } dfs1(1);dfs2(1,1);bd(1,n,1); char s[20]; while(~scanf("%s",s)){ if(s[0]=='S') break; int x,u,v,k; if(s[0]=='C'&&s[1]=='h'){ scanf("%d%d",&x,&k); int pos=p[b[x]]; up(pos,pos,1,n,1,k,1); }else if(s[0]=='C'&&s[1]=='o'){ scanf("%d%d%d",&u,&v,&k); col(u,v,k,1); }else if(s[0]=='A'){ scanf("%d%d%d",&u,&v,&k); col(u,v,k,2); }else{ scanf("%d%d",&u,&v); printf("%d\n",cal(u,v)); } } return 0; }