您的位置:首页 > 其它

树链剖分【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));}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: