我说下我的思路:
将边 A→B。
变成 a→C+C→B。
将 A→B 的边权转换为 C 的点权。
然后就是树链剖分的板子了。
玄一关,感谢 dalao。
//#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define int long long
template< typename T > inline void read(T &x)
{
char c=getchar();x=0;int f=0;
for(;!isdigit(c);c=getchar()) f|=(c=='-');
for(;isdigit(c);c=getchar()) x=((x<<3)+(x<<1)+(c^48));
x=f?-x:x;
}
const int N=800080;
int tot,head[N],n,m,a[N],cnt,dfn[N],top[N],siz[N],son[N],dep[N],fa[N],w[N];
struct edge
{
int v,net;
}e[N<<2];
void addedge(int u,int v)
{
tot++;
e[tot].v=v;
e[tot].net=head[u];
head[u]=tot;
}
void dfs1(int u,int f)
{
fa[u]=f;
siz[u]=1;
dep[u]=dep[f]+1;
for(int i=head[u];i;i=e[i].net)
{
if(e[i].v!=f)
{
dfs1(e[i].v,u);
}
else
continue;
siz[u]+=siz[e[i].v];
if(siz[e[i].v]>siz[son[u]])
{
son[u]=e[i].v;
}
}
}
void dfs2(int u,int f,int tp)
{
cnt++;
dfn[u]=cnt;
top[u]=tp;
if(son[u])dfs2(son[u],u,tp);
for(int i=head[u];i;i=e[i].net)
{
if(e[i].v==f||e[i].v==son[u])
{
continue;
}
dfs2(e[i].v,u,e[i].v);
}
}
#define mid ((l+r)>>1)
long long bian[N<<2],cha[N<<2],maxn[N<<2],minn[N<<2];
void pushup(int k)
{
bian[k]= bian[k<<1]+bian[k<<1|1];
maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
minn[k]=min(minn[k<<1],minn[k<<1|1]);
}
void build(int k,int l,int r)
{
if(l==r)
{
bian[k]=maxn[k]=minn[k]=w[l];
if(w[l]==LONG_LONG_MIN)
{
bian[k]=0;
maxn[k]=LONG_LONG_MIN;
minn[k]=LONG_LONG_MAX;
}
return;
}
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
void CHA(int k,int l,int r)
{
bian[k]=-bian[k];
int t=maxn[k];
maxn[k]=-minn[k];
minn[k]=-t;
}
void pushdown(int k,int l,int r)
{
if(cha[k]!=0)
{
cha[k<<1]^=1;
CHA(k<<1,l,mid);
cha[k<<1|1]^=1;
CHA(k<<1|1,mid+1,r);
cha[k]=0;
}
}
void modifycov(int k,int l,int r,int x,long long v)
{
if(l==r)
{
bian[k]=maxn[k]=minn[k]=v;
// cha[k]=0;
return;
}
pushdown(k,l,r);
if(x<=mid)
{
modifycov(k<<1,l,mid,x,v);
}
else
{
modifycov(k<<1|1,mid+1,r,x,v);
}
pushup(k);
}
void modifycha(int k,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
CHA(k,l,r);
return;
}
pushdown(k,l,r);
if(x<=mid)
{
modifycha(k<<1,l,mid,x,y);
}
if(y>mid)
{
modifycha(k<<1|1,mid+1,r,x,y);
}
pushup(k);
}
long long querysum(int k,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return bian[k];
}
pushdown(k,l,r);
long long ans=0;
if(x<=mid)
{
ans=querysum(k<<1,l,mid,x,y);
}
if(y>mid)
{
ans+=querysum(k<<1|1,mid+1,r,x,y);
}
return ans;
}
long long querymax(int k,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return maxn[k];
}
pushdown(k,l,r);
long long ans=LONG_LONG_MIN;
if(x<=mid)
{
ans=querymax(k<<1,l,mid,x,y);
}
if(y>mid)
{
ans=max(ans,querymax(k<<1|1,mid+1,r,x,y));
}
return ans;
}
long long querymin(int k,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return minn[k];
}
pushdown(k,l,r);
long long ans=LONG_LONG_MAX;
if(x<=mid)
{
ans=querymin(k<<1,l,mid,x,y);
}
if(y>mid)
{
ans=min(ans,querymin(k<<1|1,mid+1,r,x,y));
}
return ans;
}
long long anssum(int x,int y)
{
long long ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
{
swap(x,y);
}
ans+=querysum(1,1,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
ans+=querysum(1,1,n,dfn[x],dfn[y]);
return ans;
}
long long ansmax(int x,int y)
{
long long ans=LONG_LONG_MIN;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
{
swap(x,y);
}
int t=querymax(1,1,n,dfn[top[x]],dfn[x]);
if(t!=LONG_LONG_MAX)
{
ans=max(t,ans);
}
x=fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
int t=querymax(1,1,n,dfn[x],dfn[y]);
if(t!=LONG_LONG_MAX)
{
ans=max(t,ans);
}
return ans;
}
long long ansmin(int x,int y)
{
long long ans=LONG_LONG_MAX;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
{
swap(x,y);
}
int t=querymin(1,1,n,dfn[top[x]],dfn[x]);
if(t!=LONG_LONG_MIN)
{
ans=min(t,ans);
}
x=fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
int t=querymin(1,1,n,dfn[x],dfn[y]);
if(t!=LONG_LONG_MIN)
{
ans=min(t,ans);
}
return ans;
}
signed main()
{
// freopen("P1505_1.in","r",stdin);
// freopen("fk.out","w",stdout);
for(int i=1;i<=800050;i++)
{
a[i]=w[i]=LONG_LONG_MIN;
}
read(n);
for(int i=1;i<n;i++)
{
int x,y,z;
read(x);
read(y);
x++;
y++;
read(z);
addedge(x,i+n);
addedge(i+n,y);
addedge(y,i+n);
addedge(i+n,x);
a[i+n]=z;
}
dfs1(1,0);
dfs2(1,0,1);
int fk=n;
n*=4;
n+=3;
for(int i=1;i<=n;i++)
{
w[dfn[i]]=a[i];
}
build(1,1,n);
read(m);
while(m--)
{
string opt;
int x,y;
cin>>opt;
read(x);
read(y);
if(opt=="C")
{
modifycov(1,1,n,dfn[x+fk],y);
// cout<<"C";
continue;
}
if(opt=="N")
{
x++;
y++;
// if(x==y)
// {
// continue;
// }
// cout<<x<<' '<<y<<'\n';
modifycha(1,1,n,dfn[x],dfn[y]);
// cout<<"N";
continue;
}
if(x==y)
{
cout<<0<<'\n';
continue;
}
if(opt=="SUM")
{
x++;
y++;
// cout<<1<<' ';
cout<<anssum(x,y)<<'\n';
continue;
}
if(opt=="MAX")
{
x++;
y++;
// cout<<2<<' ';
cout<<ansmax(x,y)<<'\n';
continue;
}
if(opt=="MIN")
{
x++;
y++;
// cout<<3<<' ';
cout<<ansmin(x,y)<<'\n';
continue;
}
}
return 0;
}