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;
}