树链剖分
操作有点多的裸树剖。套路下放边权后就是打板子。注意操作的时候不要包括LCA。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 20005
#define F inline
using namespace std;
struct edge{ int nxt,to,d; }ed[N<<1];
struct tree{ int l,r,s,mx,mn,f; }t[N<<2];
int n,k,ti,a[N],w[N],h[N],tp[N],sz[N],to[N],fa[N],id[N],in[N],dep[N];
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
return l==r?EOF:*l++;
}
F int _read(){
int x=0,f=1; char ch=readc(),c;
while (!isdigit(ch)&&!isupper(ch)){ if (ch=='-') f=-1; ch=readc(); }
if (isupper(ch))
if (ch=='C'||ch=='N') return ch;
else return c=readc(),ch=readc(),c;
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x*f;
}
F void writec(int x){
if (x<0) putchar('-'),x=-x;
if (x>9) writec(x/10); putchar(x%10+48);
}
F void _write(int x){ writec(x),puts(""); }
#define addedge(x,y,z) ed[++k]=(edge){h[x],y,z},h[x]=k
void dfs1(int x){
sz[x]=1,dep[x]=dep[fa[x]]+1;
for (int i=h[x],v;i;i=ed[i].nxt)
if ((v=ed[i].to)!=fa[x]){
fa[v]=x,w[v]=ed[i].d,dfs1(v),sz[x]+=sz[v];
a[(i>>1)+(i&1)]=v; if (sz[v]>sz[to[x]]) to[x]=v;
}
}
void dfs2(int x){
if (to[in[id[x]=++ti]=x]) tp[to[x]]=tp[x],dfs2(to[x]);
for (int i=h[x],v;i;i=ed[i].nxt)
if ((v=ed[i].to)!=fa[x]&&v!=to[x])
tp[v]=v,dfs2(v);
}
F void updt(int x){
t[x].s*=-1,t[x].mn*=-1,t[x].mx*=-1;
swap(t[x].mn,t[x].mx),t[x].f^=1;
}
F void pshd(int x){ updt(x<<1),updt(x<<1|1); }
F void pshp(tree &x,tree l,tree r){
x.s=l.s+r.s,x.mx=max(l.mx,r.mx),x.mn=min(l.mn,r.mn);
}
void build(int x,int l,int r){
int p=w[in[l]],mid=l+r>>1; t[x].l=l,t[x].r=r;
if (l==r) return void(t[x]=(tree){l,r,p,p,p});
build(x<<1,l,mid),build(x<<1|1,mid+1,r);
pshp(t[x],t[x<<1],t[x<<1|1]);
}
void mdfy1(int x,int p,int w){
if (t[x].l==t[x].r) return void(t[x].s=t[x].mn=t[x].mx=w);
if (t[x].f) pshd(x),t[x].f=0; int mid=t[x].l+t[x].r>>1;
mdfy1(x<<1|(p>mid),p,w),pshp(t[x],t[x<<1],t[x<<1|1]);
}
void mdfy2(int x,int l,int r){
if (t[x].l>r||t[x].r<l) return;
if (t[x].l>=l&&t[x].r<=r) return updt(x);
if (t[x].f) pshd(x),t[x].f=0;
mdfy2(x<<1,l,r),mdfy2(x<<1|1,l,r);
pshp(t[x],t[x<<1],t[x<<1|1]);
}
tree srch(int x,int l,int r){
tree ret={0,0,0,-1e9,1e9,0},L,R;
if (t[x].l>r||t[x].r<l) return ret;
if (t[x].l>=l&&t[x].r<=r) return t[x];
if (t[x].f) pshd(x),t[x].f=0;
pshp(ret,srch(x<<1,l,r),srch(x<<1|1,l,r));
return ret;
}
F void nsrt(int x,int y){
while (tp[x]!=tp[y]){
if (dep[tp[x]]<dep[tp[y]]) swap(x,y);
mdfy2(1,id[tp[x]],id[x]),x=fa[tp[x]];
}
if (dep[x]<dep[y]) swap(x,y);
mdfy2(1,id[y]+1,id[x]);
}
F tree find(int x,int y){
tree ans={0,0,0,-1e9,1e9,0};
while (tp[x]!=tp[y]){
if (dep[tp[x]]<dep[tp[y]]) swap(x,y);
pshp(ans,ans,srch(1,id[tp[x]],id[x])),x=fa[tp[x]];
}
if (dep[x]<dep[y]) swap(x,y);
pshp(ans,ans,srch(1,id[y]+1,id[x])); return ans;
}
int main(){
n=_read();
for (int i=1,x,y,z;i<n;i++){
x=_read()+1,y=_read()+1,z=_read();
addedge(x,y,z),addedge(y,x,z);
}
dfs1(1),tp[1]=1,dfs2(1),build(1,1,n);
for (int q=_read();q;q--){
int f=_read(),x=_read()+1,y=_read()+1;
switch (f){
case 'C': mdfy1(1,id[a[x-1]],y-1); break;
case 'N': nsrt(x,y); break;
case 'U': _write(find(x,y).s); break;
case 'A': _write(find(x,y).mx); break;
case 'I': _write(find(x,y).mn); break;
}
}
return 0;
}