https://www.luogu.org/problemnew/show/P4315
题目描述
毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。
<math> <semantics> <mrow> <mi mathvariant="normal"> 爬 </mi> <mi mathvariant="normal"> 啊 </mi> <mi mathvariant="normal"> 爬 </mi> <mtext> </mtext> <mi mathvariant="normal"> 爬 </mi> <mi mathvariant="normal"> 啊 </mi> <mi mathvariant="normal"> 爬 </mi> </mrow> <annotation encoding="application/x-tex"> 爬啊爬~爬啊爬 </annotation> </semantics> </math>爬啊爬 爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~ “毛景树”上有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之间树枝上毛毛果个数最多有多少个。
题意:给定一颗树,有4种操作:
1.查询两点间最大边权
2.两点间边权加v
3.两点间边赋值v
4.第i条边权值变成v
思路:第四种操作等价于第3种。难点在于线段树操作,想明白怎么同时维护setv和addv两个标记这道题就是水题了。
这道题就是同时维护两个标记的https://blog.csdn.net/Wen_Yongqi/article/details/90209453
#include<bits/stdc++.h>
using namespace std;
#define maxn (100000+100)
vector<int> G[maxn];
int dfs_clock;
int n,from[maxn],to[maxn],w[maxn],id[maxn],top[maxn],deep[maxn],sz[maxn],fa[maxn],son[maxn];
char cmd[20];
int op,ql,qr,val;
struct Edge{
int u,v,w;
};
vector<Edge> edges;
int addv[maxn*4],setv[maxn*4],sumv[maxn*4],minv[maxn*4],maxv[maxn*4];
int _sum,_min,_max;
void maintain(int o,int l,int r)
{
if(setv[o]!=-1)
{
sumv[o]=setv[o]*(r-l+1);
minv[o]=maxv[o]=setv[o];
}
else
{
sumv[o]=sumv[o*2]+sumv[o*2+1];
minv[o]=min(minv[o*2],minv[o*2+1]);
maxv[o]=max(maxv[o*2],maxv[o*2+1]);
}
sumv[o]+=addv[o]*(r-l+1);
minv[o]+=addv[o];
maxv[o]+=addv[o];
}
void build(int o,int l,int r)
{
if(l==r)setv[o]=w[l];
else
{
setv[o]=-1;
int mid=(l+r)/2;
build(o*2,l,mid);
build(o*2+1,mid+1,r);
}
maintain(o,l,r);
}
void pushdown(int o)
{
if(setv[o]!=-1)
{
setv[o*2]=setv[o*2+1]=setv[o];
addv[o*2]=addv[o*2+1]=0;
setv[o]=-1;
}
if(addv[o]!=0)
{
addv[o*2]+=addv[o];
addv[o*2+1]+=addv[o];
addv[o]=0;
}
}
void update(int o,int l,int r)
{
if(ql<=l&&qr>=r)
{
if(op==2){setv[o]=val;addv[o]=0;}
else addv[o]+=val;
}
else
{
int mid=(l+r)/2;
pushdown(o);
if(ql<=mid)update(o*2,l,mid);else maintain(o*2,l,mid);
if(qr>mid)update(o*2+1,mid+1,r);else maintain(o*2+1,mid+1,r);
}
maintain(o,l,r);
}
void query(int o,int l,int r)
{
if(ql<=l&&qr>=r)
{
_sum+=sumv[o];
_min=min(_min,minv[o]);
_max=max(_max,maxv[o]);
}
else
{
int mid=(l+r)/2;
pushdown(o);
maintain(o*2,l,mid);maintain(o*2+1,mid+1,r);
maintain(o,l,r);
if(ql<=mid)query(o*2,l,mid);
if(qr>mid)query(o*2+1,mid+1,r);
}
}
void dfs1(int u,int f)
{
deep[u]=deep[f]+1;
fa[u]=f;
sz[u]=1;
int maxx=0;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==f)continue;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>maxx){maxx=sz[v];son[u]=v;}
}
}
void dfs2(int u,int up)
{
top[u]=up;
id[u]=++dfs_clock;
if(son[u])dfs2(son[u],up);
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
void Update(int u,int v)
{
int tp1=top[u],tp2=top[v];
while(tp1!=tp2)
{
if(deep[tp1]<deep[tp2]){swap(tp1,tp2);swap(u,v);}
ql=id[tp1],qr=id[u];
update(1,1,n);
u=fa[tp1];
tp1=top[u];
}
if(u==v)return;
if(deep[u]>deep[v])swap(u,v);
ql=id[u]+1,qr=id[v];
update(1,1,n);
}
int Query(int u,int v)
{
_max=0;
int tp1=top[u],tp2=top[v];
while(tp1!=tp2)
{
if(deep[tp1]<deep[tp2]){swap(tp1,tp2);swap(u,v);}
ql=id[tp1],qr=id[u];
query(1,1,n);
u=fa[tp1];
tp1=top[u];
}
if(u==v)return _max;
if(deep[u]>deep[v])swap(u,v);
ql=id[u]+1,qr=id[v];
query(1,1,n);
return _max;
}
int main()
{
//freopen("input.in","r",stdin);
int x,y,z;
cin>>n;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
G[x].push_back(y);
G[y].push_back(x);
edges.push_back((Edge){x,y,z});
}
dfs1(1,0);
dfs2(1,1);
for(int i=0;i<edges.size();i++)
{
Edge &e=edges[i];
if(deep[e.u]>deep[e.v])w[id[e.u]]=e.w;
else w[id[e.v]]=e.w;
}
build(1,1,n);
while(scanf("%s",cmd)&&cmd[0]!='S')
{ //op:2-setv op:1-addv
if(cmd[0]=='M')
{
scanf("%d%d",&x,&y);
printf("%d\n",Query(x,y));
}
else if(cmd[0]=='A')
{
scanf("%d%d%d",&x,&y,&z);
op=1;val=z;
Update(x,y);
}
else if(cmd[1]=='o')
{
scanf("%d%d%d",&x,&y,&z);
op=2;val=z;
Update(x,y);
}
else
{
scanf("%d%d",&x,&z);
op=2;val=z;
y=edges[x-1].v;
x=edges[x-1].u;
Update(x,y);
}
}
return 0;
}