树链剖分【p4315】月下"毛景树"
2018-10-16 19:47
239 查看
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
对于毛毛虫的每个询问操作,输出一个答案。
树剖裸题,注意边权转点权,
这里要找到编号为\(k\)的边所连的深度深的点.
我们把边权传递给下面深度较深的点,是可以保证每个点价值唯一的.
只需要维护区间覆盖和区间最大值即可了.
注意区间覆盖的优先级高于区间加
代码
#include<cstdio> #include<cstring> #include<iostream> #include<cctype> #define int long long #define ls o<<1 #define rs o<<1|1 #define R register #define N 100008 using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int head ,tot; struct cod{int u,v,w,fr;}edge[N<<2]; inline void add(int x,int y,int z) { edge[++tot].u=head[x]; edge[tot].fr=x; edge[tot].v=y; edge[tot].w=z; head[x]=tot; } int size ,son ,f ,depth ,val ; void dfs1(int u,int fa,int dis) { val[u]=dis;f[u]=fa;size[u]=1;depth[u]=depth[fa]+1; for(R int i=head[u];i;i=edge[i].u) { if(edge[i].v==fa)continue; dfs1(edge[i].v,u,edge[i].w); size[u]+=size[edge[i].v]; if(son[u]==-1 or size[son[u]]<size[edge[i].v]) son[u]=edge[i].v; } } int dfn ,fdfn ,idx,top ; void dfs2(int u,int t) { top[u]=t;dfn[u]=++idx;fdfn[idx]=u; if(son[u]==-1)return; dfs2(son[u],t); for(R int i=head[u];i;i=edge[i].u) { if(dfn[edge[i].v])continue; dfs2(edge[i].v,edge[i].v); } } int n; char s[8]; int tr[N<<2],tg1[N<<2],tg2[N<<2]; inline void up(int o) { tr[o]=max(tr[ls],tr[rs]); return; } inline void down(int o,int l,int r) { if(tg1[o]>=0) { tr[ls]=tr[rs]=tg1[ls]=tg1[rs]=tg1[o]; tg1[o]=-1;tg2[ls]=tg2[rs]=0; } if(tg2[o]) { tr[ls]+=tg2[o];tr[rs]+=tg2[o]; tg2[ls]+=tg2[o];tg2[rs]+=tg2[o]; tg2[o]=0; } } void build(int o,int l,int r) { tg1[o]=-1; if(l==r) { tr[o]=val[fdfn[l]]; return; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); up(o); } void change1(int o,int l,int r,int x,int y,int k)//区间覆盖. { if(x<=l and y>=r) { tr[o]=tg1[o]=k; tg2[o]=0; return; } down(o,l,r); int mid=(l+r)>>1; if(x<=mid)change1(ls,l,mid,x,y,k); if(y>mid)change1(rs,mid+1,r,x,y,k); up(o); } void change2(int o,int l,int r,int x,int y,int k)//区间增加. { if(x<=l and y>=r) { tr[o]+=k;tg2[o]+=k; return; } down(o,l,r); int mid=(l+r)>>1; if(x<=mid)change2(ls,l,mid,x,y,k); if(y>mid)change2(rs,mid+1,r,x,y,k); up(o); } int query(int o,int l,int r,int x,int y) { if(x<=l and y>=r)return tr[o]; down(o,l,r); int mid=(l+r)>>1,res=-2147483647; if(x<=mid)res=max(res,query(ls,l,mid,x,y)); if(y>mid)res=max(res,query(rs,mid+1,r,x,y)); return res; } inline void tchange1(int x,int y,int k) { int fx=top[x],fy=top[y]; while(fx!=fy) { if(depth[fx]>depth[fy]) { change1(1,1,idx,dfn[fx],dfn[x],k); x=f[fx]; } else { change1(1,1,idx,dfn[fy],dfn[y],k); y=f[fy]; } fx=top[x],fy=top[y]; } if(x==y)return; if(dfn[x]>dfn[y])swap(x,y); change1(1,1,idx,dfn[x]+1,dfn[y],k); return; } inline void tchange2(int x,int y,int k) { int fx=top[x],fy=top[y]; while(fx!=fy) { if(depth[fx]>depth[fy]) { change2(1,1,idx,dfn[fx],dfn[x],k); x=f[fx]; } else { change2(1,1,idx,dfn[fy],dfn[y],k); y=f[fy]; } fx=top[x],fy=top[y]; } if(x==y)return; if(dfn[x]>dfn[y])swap(x,y); change2(1,1,idx,dfn[x]+1,dfn[y],k); return; } inline int tquery(int x,int y) { int fx=top[x],fy=top[y],res=-2147483647; while(fx!=fy) { if(depth[fx]>depth[fy]) { res=max(res,query(1,1,idx,dfn[fx],dfn[x])); x=f[fx]; } else { res=max(res,query(1,1,idx,dfn[fy],dfn[y])); y=f[fy]; } fx=top[x],fy=top[y]; } if(x==y)return res; if(dfn[x]>dfn[y])swap(x,y); res=max(res,query(1,1,idx,dfn[x]+1,dfn[y])); return res; } signed main() { in(n);memset(son,-1,sizeof son); for(R int i=1,x,y,z;i<n;i++) { in(x),in(y),in(z); add(x,y,z),add(y,x,z); } dfs1(1,0,0);dfs2(1,1);build(1,1,idx); while(1) { scanf("%s",s); if(s[0]=='S')break; R int x,y,k; if(s[0]=='C' and s[1]=='h') { in(x),in(k); x*=2; if(depth[edge[x].fr]>depth[edge[x].v]) x=edge[x].fr; else x=edge[x].v; change1(1,1,idx,dfn[x],dfn[x],k); }//单点修改 else if(s[0]=='C' and s[1]=='o') {in(x),in(y),in(k);tchange1(x,y,k);}//区间覆盖 else if(s[0]=='A')//区间增加 {in(x),in(y),in(k);tchange2(x,y,k);} else if(s[0]=='M') {in(x),in(y);printf("%lld\n",tquery(x,y));} } }
相关文章推荐
- [bzoj1984]月下“毛景树” 树链剖分
- 【BZOJ1984】月下“毛景树”-树链剖分
- [BZOJ1984]月下“毛景树”解题报告|树链剖分
- BZOJ 1984 月下“毛景树” 树链剖分
- Bzoj 1984: 月下“毛景树” 树链剖分
- 树链剖分 月下毛景树
- [BZOJ1984]月下“毛景树”(树链剖分)
- 【BZOJ-1984】月下“毛景树” 树链剖分
- 【树链剖分】【分块】【最近公共祖先】【块状树】bzoj1984 月下“毛景树”
- 【bzoj1984】【坑】月下“毛景树” 树链剖分
- bzoj 1984: 月下“毛景树” (树链剖分)
- [BZOJ1984]月下“毛景树”(树链剖分)
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
- bzoj1984 月下“毛景树”(边权的树链剖分)
- BZOJ 1984: 月下“毛景树”( 树链剖分 )
- [BZOJ1984] 月下“毛景树”|树链剖分|线段树
- bzoj1984 月下“毛景树”树链剖分 线段树
- 【BZOJ1984】月下“毛景树” 树链剖分+线段树
- BZOJ1984: 月下“毛景树”
- BZOJ1984 月下“毛景树”