这题在线段树中需要成段覆盖和成段加,在处理时需要当心。
同时需要将边权转换成点权。
题目链接
#include<iostream>
#include<cstdio>
using namespace std;
int n,tot,lable,root,f[100100],lazy1[800800],lazy2[800800],a[800800],Next[200010],head[200100],tree[200100],val[200100];
int Number[200100],dep[100100],fa[100100],size[100100],son[100100],bian[100100],tid[100100],top[100100],num[100100];
bool visit[100100];
int Max(int x,int y){ return (x>y)?x:y;}
void up(int x) {a[x]=Max(a[x*2],a[x*2+1]);}
int swap(int &x,int &y) {int t=x;x=y;y=t;}
void down(int x)
{
if (lazy1[x]!=-1)
{
lazy1[x*2]=lazy1[x*2+1]=lazy1[x];
a[x*2]=a[x*2+1]=lazy1[x];
lazy2[x*2]=lazy2[x*2+1]=0;
lazy1[x]=-1;
}
if (lazy2[x]!=0)
{
lazy2[x*2]+=lazy2[x];
lazy2[x*2+1]+=lazy2[x];
a[x*2]+=lazy2[x];
a[x*2+1]+=lazy2[x];
lazy2[x]=0;
}
}
void add(int x,int y,int z,int number)
{
tot++;
Next[tot]=head[x];
head[x]=tot;
tree[tot]=y;
val[tot]=z;
Number[tot]=number;
}
void dfs1(int x,int depth,int father)
{
dep[x]=depth;fa[x]=father;size[x]=1;
visit[x]=true;son[x]=0;
int maxsize=0;
for (int i=head[x];i;i=Next[i])
if (!visit[tree[i]])
{
f[tree[i]]=val[i];bian[Number[i]]=tree[i];
dfs1(tree[i],depth+1,x);
size[x]+=size[tree[i]];
if (size[tree[i]]>maxsize) maxsize=size[tree[i]],son[x]=tree[i];
}
}
void dfs2(int x,int ancestor)
{
visit[x]=true;
lable++;tid[x]=lable;num[lable]=x;top[x]=ancestor;
if (son[x]!=0) dfs2(son[x],ancestor);
for (int i=head[x];i;i=Next[i])
if (!visit[tree[i]]) dfs2(tree[i],tree[i]);
}
void build(int l,int r,int id)
{
lazy1[id]=-1;lazy2[id]=0;
if (l==r)
{
a[id]=f[num[l]];
return;
}
int mid=(l+r)/2;
build(l,mid,id*2);
build(mid+1,r,id*2+1);
up(id);
}
int query(int x,int y,int l,int r,int id)
{
if (l>y||r<x||x>y) return -1<<29;
if (x<=l&&r<=y) return a[id];
int mid=(l+r)/2;
down(id);
return Max(query(x,y,l,mid,id*2),query(x,y,mid+1,r,id*2+1));
}
void cover(int x,int y,int l,int r,int id,int d)
{
if (l>y||r<x||x>y) return;
if (x<=l&&r<=y)
{
lazy1[id]=d;
lazy2[id]=0;
a[id]=d;
return;
}
int mid=(l+r)/2;
down(id);
cover(x,y,l,mid,id*2,d);
cover(x,y,mid+1,r,id*2+1,d);
up(id);
}
void change(int x,int y,int l,int r,int id,int d)
{
if (l>y||r<x||x>y) return;
if (x<=l&&r<=y)
{
//down(id);
if (lazy1[id]!=-1) lazy1[id]+=d;else lazy2[id]+=d;
a[id]+=d;
return;
}
int mid=(l+r)/2;
down(id);
change(x,y,l,mid,id*2,d);
change(x,y,mid+1,r,id*2+1,d);
up(id);
}
int Query(int x,int y)
{
int ans=-1<<30;
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
ans=Max(ans,query(tid[top[x]],tid[x],1,n,1));
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
ans=Max(ans,query(tid[x]+1,tid[y],1,n,1));
return ans;
}
void Cover(int x,int y,int d)
{
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
cover(tid[top[x]],tid[x],1,n,1,d);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
cover(tid[x]+1,tid[y],1,n,1,d);
}
void Add(int x,int y,int d)
{
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
change(tid[top[x]],tid[x],1,n,1,d);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
change(tid[x]+1,tid[y],1,n,1,d);
}
int main()
{
scanf("%d",&n);
tot=lable=0;
for (int i=1;i<=n-1;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z,i);add(y,x,z,i);
}
root=1;
f[root]=-1<<30;
for (int i=1;i<=n;i++) visit[i]=false;
dfs1(1,1,0);
for (int i=1;i<=n;i++) visit[i]=false;
dfs2(1,1);
build(1,n,1);
char s[100];
while (true)
{
scanf("%s",s);
if (s[0]=='S') break;
int x,y;
scanf("%d%d",&x,&y);
if (s[0]=='M')
{
printf("%d\n",Query(x,y));
continue;
}
if (s[0]=='C'&&s[1]=='h')
{
cover(tid[bian[x]],tid[bian[x]],1,n,1,y);
continue;
}
int z;
scanf("%d",&z);
if (s[0]=='C') Cover(x,y,z);
if (s[0]=='A') Add(x,y,z);
}
return 0;
}