#樹鏈剖分,線段樹#洛谷 1505 [國家集訓隊]旅遊
阿新 • • 發佈:2020-09-19
分析
邊權那就將邊權變為深度更大的點的點權,
相反數會影響最值和求和,剩下就是模板了
注意兩次相反數的標記要抵消掉
程式碼
#include <cstdio> #include <cctype> #define rr register using namespace std; const int N=200011; struct node{int y,w,next;}e[N<<1]; int top[N],fat[N],wsum[N<<2],wmin[N<<2],wmax[N<<2],lazy[N<<2]; int tot,n,K=1,as[N],dfn[N],dep[N],big[N],son[N],A[N],a[N]; inline signed iut(){ rr int ans=0,f=1; rr char c=getchar(); while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans*f; } inline void print(int ans){ if (ans<0) putchar('-'),ans=-ans; if (ans>9) print(ans/10); putchar(ans%10+48); } inline void Swap(int &x,int &y){rr int t=x; x=y; y=t;} inline signed min(int a,int b){return a<b?a:b;} inline signed max(int a,int b){return a>b?a:b;} inline void pup(int k){ wsum[k]=wsum[k<<1]+wsum[k<<1|1], wmin[k]=min(wmin[k<<1],wmin[k<<1|1]), wmax[k]=max(wmax[k<<1],wmax[k<<1|1]); } inline void ptag(int k){ Swap(wmin[k],wmax[k]),wsum[k]=-wsum[k], wmin[k]=-wmin[k],wmax[k]=-wmax[k],lazy[k]^=1; } inline void pdown(int k){ptag(k<<1),ptag(k<<1|1),lazy[k]=0;} inline void build(int k,int l,int r){ if (l==r){ wmin[k]=wmax[k]=wsum[k]=a[l]; return; } rr int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); pup(k); } inline void single(int k,int l,int r,int x,int y){ if (l==r) {wmin[k]=wmax[k]=wsum[k]=y,lazy[k]=0; return;} rr int mid=(l+r)>>1; if (lazy[k]) pdown(k); if (x<=mid) single(k<<1,l,mid,x,y); else single(k<<1|1,mid+1,r,x,y); pup(k); } inline void update(int k,int l,int r,int x,int y){ if (l==x&&r==y) {ptag(k); return;} rr int mid=(l+r)>>1; if (lazy[k]) pdown(k); if (y<=mid) update(k<<1,l,mid,x,y); else if (x>mid) update(k<<1|1,mid+1,r,x,y); else update(k<<1,l,mid,x,mid),update(k<<1|1,mid+1,r,mid+1,y); pup(k); } inline signed query(int k,int l,int r,int x,int y,int z){ if (l==x&&r==y){ if (!z) return wmin[k]; else if (z==1) return wmax[k]; else return wsum[k]; } rr int mid=(l+r)>>1; if (lazy[k]) pdown(k); if (y<=mid) return query(k<<1,l,mid,x,y,z); else if (x>mid) return query(k<<1|1,mid+1,r,x,y,z); else{ rr int ans1=query(k<<1,l,mid,x,mid,z); rr int ans2=query(k<<1|1,mid+1,r,mid+1,y,z); if (z==1) return max(ans1,ans2); else if (z==2) return ans1+ans2; else return min(ans1,ans2); } } inline void Update(int x,int y){ for (;top[x]!=top[y];x=fat[top[x]]){ if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y; update(1,1,n,dfn[top[x]],dfn[x]); } if (dep[x]>dep[y]) x^=y,y^=x,x^=y; if (dfn[x]<dfn[y]) update(1,1,n,dfn[x]+1,dfn[y]); } inline signed Query(int x,int y,int z){ rr int ans=(z==2)?0:((z==1)?-1001:1001); for (;top[x]!=top[y];x=fat[top[x]]){ if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y; rr int tans=query(1,1,n,dfn[top[x]],dfn[x],z); if (z==1) ans=max(ans,tans); else if (z==2) ans+=tans; else ans=min(ans,tans); } if (dep[x]>dep[y]) x^=y,y^=x,x^=y; if (dfn[x]<dfn[y]){ rr int tans=query(1,1,n,dfn[x]+1,dfn[y],z); if (z==1) ans=max(ans,tans); else if (z==2) ans+=tans; else ans=min(ans,tans); } return ans; } inline void dfs1(int x,int fa){ dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1; for (rr int i=as[x],mson=-1;i;i=e[i].next) if (e[i].y!=fa){ dfs1(e[i].y,x); A[e[i].y]=e[i].w; son[x]+=son[e[i].y]; if (son[e[i].y]>mson) big[x]=e[i].y,mson=son[e[i].y]; } } inline void dfs2(int x,int linp){ dfn[x]=++tot,top[x]=linp,a[dfn[x]]=A[x]; if (!big[x]) return; dfs2(big[x],linp); for (rr int i=as[x];i;i=e[i].next) if (e[i].y!=fat[x]&&e[i].y!=big[x]) dfs2(e[i].y,e[i].y); } signed main(){ n=iut(); for (rr int i=1;i<n;++i){ rr int x=iut()+1,y=iut()+1,w=iut(); e[++K]=(node){y,w,as[x]},as[x]=K; e[++K]=(node){x,w,as[y]},as[y]=K; } dfs1(1,0),dfs2(1,1),build(1,1,n); rr char ss[5]; for (rr int T=iut();T;--T){ scanf("%s",ss); rr int x=iut()+1,y=iut()+1; switch (ss[0]){ case 'C':{ --x; --y; rr int X=e[x<<1].y,Y=e[x<<1|1].y; if (dep[X]<dep[Y]) X^=Y,Y^=X,X^=Y; single(1,1,n,dfn[X],y); break; } case 'N':{ Update(x,y); break; } case 'S':{ print(Query(x,y,2)),putchar(10); break; } case 'M':{ if (ss[1]=='I') print(Query(x,y,0)); else print(Query(x,y,1)); putchar(10); break; } } } return 0; }