题目描述:
咕了几个月的题解:
无脑$splay$+树剖。
论复制粘贴在考场上拉分的重要作用。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 50050; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x = f*c; } int n,m,Rt,hed[N],cnt; struct EG { int to,nxt; }e[N<<1]; void ae(int f,int t) { e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt; } int dep[N],siz[N],tp[N],son[N],fa[N],tin[N],tout[N],tim,pla[N]; void dfs1(int u,int f) { fa[u]=f,siz[u]=1,dep[u]=dep[f]+1; for(int j=hed[u],to;j;j=e[j].nxt)if((to=e[j].to)!=f) { dfs1(to,u),siz[u]+=siz[to]; if(siz[to]>siz[son[u]])son[u]=to; } } void dfs2(int u,int Top) { tp[u]=Top,tin[u]=++tim,pla[tim]=u; if(son[u]) { dfs2(son[u],Top); for(int j=hed[u],to;j;j=e[j].nxt) if((to=e[j].to)!=fa[u]&&to!=son[u])dfs2(to,to); } tout[u]=tim; } int get_lca(int x,int y) { while(tp[x]!=tp[y]) { if(dep[tp[x]]<dep[tp[y]])swap(x,y); x = fa[tp[x]]; } return dep[x]<dep[y]?x:y; } struct Splay { int w[N],mx[N],mn[N],rt,rtt,fa[N],ch[N][2],siz[N]; ll tag[N],s[N]; bool res[N]; void add(int u,ll d) { if(u)w[u]+=d,tag[u]+=d,s[u]+=d*siz[u],mx[u]+=d,mn[u]+=d; } void rever(int u) { if(u)swap(ch[u][0],ch[u][1]),res[u]^=1; } void pushdown(int u) { if(tag[u]) { add(ch[u][0],tag[u]); add(ch[u][1],tag[u]); tag[u]=0; } if(res[u]) { rever(ch[u][0]); rever(ch[u][1]); res[u] = 0; } } void update(int x) { s[x]=s[ch[x][0]]+s[ch[x][1]]+w[x]; siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; mx[x]=max(w[x],max(mx[ch[x][0]],mx[ch[x][1]])); mn[x]=min(w[x],min(mn[ch[x][0]],mn[ch[x][1]])); } void rotate(int x) { int y = fa[x],z = fa[y],k = (ch[y][1]==x); ch[z][ch[z][1]==y]=x,fa[x]=z; ch[y][k]=ch[x][!k],fa[ch[x][!k]]=y; ch[x][!k]=y,fa[y]=x; update(y),update(x); } int sta[N],tl; void down(int x) { tl = 0; while(x)sta[++tl]=x,x=fa[x]; while(tl)pushdown(sta[tl--]); } void splay(int x,int goal) { down(x); while(fa[x]!=goal) { int y = fa[x],z = fa[y]; if(z!=goal) (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y); rotate(x); } if(!goal)rt=x; } void splayy(int x,int goal) { down(x); while(fa[x]!=goal) { int y = fa[x],z = fa[y]; if(z!=goal) (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y); rotate(x); } if(!goal)rtt=x; } int build(int l,int r,int f) { if(l>r)return 0; int mid = (l+r)>>1; fa[mid] = f;if(!f)rt=mid; ch[mid][0] = build(l,mid-1,mid); ch[mid][1] = build(mid+1,r,mid); update(mid);return mid; } void init() { fa[n+4]=n+3;ch[n+3][1]=n+4;rtt=n+3; siz[n+3]=2,siz[n+4]=1; mn[0]=0x3f3f3f3f,mx[0]=-0x3f3f3f3f; } int get_kth(int u,int k) { pushdown(u); int tmp = siz[ch[u][0]]; if(k<=tmp)return get_kth(ch[u][0],k); else if(k==tmp+1)return u; else return get_kth(ch[u][1],k-1-tmp); } void split(int l,int r) { l = get_kth(rt,l),r = get_kth(rt,r+2); splay(l,0),splay(r,l); } void splitt(int l,int r) { l = get_kth(rtt,l),r = get_kth(rtt,r+2); splayy(l,0),splayy(r,l); } int get_kw(int k) { int x = get_kth(rt,k+1);return w[x]; } ll get_sum(int l,int r) { split(l,r); return s[ch[ch[rt][1]][0]]; } int get_max(int l,int r) { split(l,r);return mx[ch[ch[rt][1]][0]]; } int get_min(int l,int r) { split(l,r);return mn[ch[ch[rt][1]][0]]; } void Inc(int l,int r,int d) { split(l,r); add(ch[ch[rt][1]][0],d); update(ch[rt][1]),update(rt); } void mr(int l,int r) { split(l,r);int now = get_kth(rtt,2),las = ch[ch[rt][1]][0]; splayy(now,0);fa[las]=n+3,ch[n+3][1]=las,ch[ch[rt][1]][0]=0; update(ch[rt][1]),update(rt),update(n+3),update(now); } void rvs() { splayy(n+3,0),splayy(n+4,n+3); rever(ch[ch[rtt][1]][0]); } void ml(int l,int r) { int xl = get_kth(rt,l),xr = get_kth(rt,l+1); splay(xr,0),splay(xl,xr); splitt(1,r-l+1);int now = ch[ch[rtt][1]][0]; ch[ch[rtt][1]][0]=0,ch[ch[rt][0]][1]=now,fa[now]=ch[rt][0]; update(ch[rt][0]),update(rt),update(ch[rtt][1]),update(rtt); } }tr; char op[10]; int lst[N],rst[N],tl; ll queryS(int x,int y) { ll ret = 0; while(tp[x]!=tp[y]) { ret+=tr.get_sum(tin[tp[x]],tin[x]); x = fa[tp[x]]; } return ret+tr.get_sum(tin[y],tin[x]); } int queryMax(int x,int y) { int ret = -0x3f3f3f3f; while(tp[x]!=tp[y]) { ret = max(ret,tr.get_max(tin[tp[x]],tin[x])); x = fa[tp[x]]; } return max(ret,tr.get_max(tin[y],tin[x])); } int queryMin(int x,int y) { int ret = 0x3f3f3f3f; while(tp[x]!=tp[y]) { ret = min(ret,tr.get_min(tin[tp[x]],tin[x])); x = fa[tp[x]]; } return min(ret,tr.get_min(tin[y],tin[x])); } int main() { read(n),read(m),read(Rt); for(int i=1,u,v;i<n;i++) { read(u),read(v); ae(u,v),ae(v,u); } dfs1(Rt,0),dfs2(Rt,Rt); tr.build(1,n+2,0);tr.init(); for(int i=1,x,y,w;i<=m;i++) { scanf("%s",op+1),read(x),read(y); if(dep[x]>dep[y])swap(x,y); if(op[1]=='I'&&op[3]=='c') { read(w); while(tp[y]!=tp[x]) { tr.Inc(tin[tp[y]],tin[y],w); y = fa[tp[y]]; } tr.Inc(tin[x],tin[y],w); }else if(op[1]=='I'&&op[3]=='v') { tl = 0; while(tp[y]!=tp[x]) { lst[++tl]=tin[tp[y]],rst[tl]=tin[y]; tr.mr(lst[tl],rst[tl]); y = fa[tp[y]]; } lst[++tl]=tin[x],rst[tl]=tin[y]; tr.mr(lst[tl],rst[tl]); tr.rvs(); for(int j=tl;j>=1;j--) tr.ml(lst[j],rst[j]); }else if(op[1]=='S') { int Lca = get_lca(x,y); ll ans = queryS(x,Lca); ans+=queryS(y,Lca); ans-=tr.get_kw(tin[Lca]); printf("%lld ",ans); }else if(op[1]=='M'&&op[2]=='a') { int Lca = get_lca(x,y); int ans = max(queryMax(x,Lca),queryMax(y,Lca)); printf("%d ",ans); }else { int Lca = get_lca(x,y); int ans = min(queryMin(x,Lca),queryMin(y,Lca)); printf("%d ",ans); } } return 0; }