版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/83010350
题解:不错的树链剖分练习题。
又是毒瘤仙人掌,先把环缩起来,然后链剖维护重链上相邻的环的最小值。
对于轻边特殊处理,此时要对每个环再维护一个线段树。
时间复杂度。
#include <bits/stdc++.h> using namespace std; typedef pair <int,int> pii; const int RLEN=1<<18|1; inline char nc() { static char ibuf[RLEN],*ib,*ob; (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin)); return (ib==ob) ? -1 : *ib++; } inline int rd() { char ch=nc(); int i=0,f=1; while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();} while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();} return i*f; } const int N=2e5+50, inf=2e9; int n,m,k,scc,cnt; int anc[N],vis[N],dep[N]; int id[N],bl[N],head[N],tail[N]; int fa[N],top[N],sze[N],son[N],st[N],ind; struct edge {int x,y,w;} e[N]; map <int,int> Mp[N]; vector <int> gi[N]; struct ST { int mn[N*4]; inline void inc(int k,int l,int r,int p,int v) { if(l==r) {mn[k]=v; return;} int mid=(l+r)>>1; (p<=mid) ? inc(k<<1,l,mid,p,v) : inc(k<<1|1,mid+1,r,p,v); mn[k]=min(mn[k<<1],mn[k<<1|1]); } inline int ask(int k,int l,int r,int L,int R) { if(L<=l && r<=R) return mn[k]; int mid=(l+r)>>1; if(R<=mid) return ask(k<<1,l,mid,L,R); else if(L>mid) return ask(k<<1|1,mid+1,r,L,R); else return min(ask(k<<1,l,mid,L,R),ask(k<<1|1,mid+1,r,L,R)); } inline void inc(int pos,int v) {inc(1,1,n,pos,v);} inline int ask(int l,int r) {return (l>r) ? inf : ask(1,1,n,l,r);} } tree,chain,cir; inline int ga(int x) {return (anc[x]==x) ? x : (anc[x]=ga(anc[x]));} inline void add(int x,int y) {gi[x].push_back(y); gi[y].push_back(x);} inline int lca(int x,int y) { while(top[x]^top[y]) (dep[top[x]]>dep[top[y]]) ? (x=fa[top[x]]) : (y=fa[top[y]]); return (dep[x]<dep[y]) ? x : y; } inline void dfs(int x,int f) { sze[x]=1; fa[x]=f; dep[x]=dep[f]+1; for(auto v:gi[x]) if(v^f) { dfs(v,x); sze[x]+=sze[v]; if(sze[son[x]]<sze[v]) son[x]=v; } } inline void Dfs(int x,int f) { st[x]=++ind; top[x]=f; if(son[x]) Dfs(son[x],f); for(auto v:gi[x]) if(v^fa[x] && v^son[x]) Dfs(v,v); } inline void work(int x,int y) { static int ql[N],qr[N]; ql[0]=qr[0]=0; while(x^y) (dep[x]<dep[y]) ? (qr[++qr[0]]=y, y=fa[y]) : (ql[++ql[0]]=x, x=fa[x]); ql[++ql[0]]=x; while(qr[0]) ql[++ql[0]]=qr[qr[0]--]; ++scc; head[scc]=cnt+1; tail[scc]=cnt+ql[0]; for(int i=1;i<=ql[0];i++) id[ql[i]]=++cnt, bl[ql[i]]=scc; } inline int calc(int a,int b) { if(a==b) return inf; if(id[a]>id[b]) swap(a,b); int mn1=cir.ask(id[a]+1,id[b]); int mn2=cir.ask(id[b]+1,tail[bl[b]]); mn2=min(mn2,cir.ask(head[bl[a]],id[a])); return min(INF,mn1+mn2; } inline void change(int i,int w) { if(bl[e[i].x]^bl[e[i].y]) { int x=(fa[bl[e[i].x]]==bl[e[i].y]) ? bl[e[i].x] : bl[e[i].y]; tree.inc(st[x],w); } else { int x=e[i].x, y=e[i].y; if(id[x]>id[y]) swap(x,y); if(id[x]==id[y]-1) cir.inc(id[y],w); else cir.inc(id[x],w); if(fa[bl[x]] && son[bl[x]]) { int r=Mp[bl[x]][son[bl[x]]]; int a=(bl[e[r].x]==bl[x]) ? e[r].x : e[r].y; r=Mp[bl[x]][fa[bl[x]]]; int b=(bl[e[r].x]==bl[x]) ? e[r].x : e[r].y; chain.inc(st[bl[x]],calc(a,b)); } } } inline void pre_calc() { for(int i=1;i<=scc;i++) if(fa[i] && son[i]) { if(head[i]==tail[i]) chain.inc(st[i],inf); } else chain.inc(st[i],inf); for(int i=1;i<=m;i++) change(i,e[i].w); } inline int ask_tree(int x,int f) { int ans=inf; while(top[x]^top[f]) ans=min(ans,tree.ask(st[top[x]],st[x])), x=fa[top[x]]; if(x^f) ans=min(ans,tree.ask(st[son[f]],st[x])); return ans; } inline pii ask_cir(int last,int f) { int ans=inf; while(top[bl[last]]^top[f]) { int r=Mp[bl[last]][fa[bl[last]]]; int a=(bl[e[r].x]==bl[last]) ? e[r].x : e[r].y; ans=min(ans,calc(last,a)); ans=min(ans,chain.ask(st[top[bl[last]]],st[bl[last]]-1)); r=Mp[top[bl[last]]][fa[top[bl[last]]]]; last=(bl[e[r].x]==top[bl[last]]) ? e[r].y : e[r].x; } if(bl[last]^f) { int r=Mp[bl[last]][fa[bl[last]]]; int a=(bl[e[r].x]==bl[last]) ? e[r].x : e[r].y; ans=min(ans,calc(last,a)); ans=min(ans,chain.ask(st[f]+1,st[bl[last]]-1)); r=Mp[son[f]][f]; last=(bl[e[r].x]==f) ? e[r].x : e[r].y; } return pii(ans,last); } int main() { n=rd(), m=rd(); for(int i=1;i<=n;i++) anc[i]=i; for(int i=1;i<=m;i++) e[i].x=rd(), e[i].y=rd(), e[i].w=rd(); for(int i=1;i<=m;i++) if(ga(e[i].x)^ga(e[i].y)) { anc[ga(e[i].x)]=ga(e[i].y); vis[i]=1; add(e[i].x,e[i].y); } dfs(1,0); for(int i=1;i<=m;i++) if(!vis[i]) work(e[i].x,e[i].y); for(int i=1;i<=n;i++) if(!bl[i]) bl[i]=++scc, id[i]=++cnt; for(int i=1;i<=n;i++) gi[i].clear(); for(int i=1;i<=m;i++) if(bl[e[i].x]^bl[e[i].y]) { Mp[bl[e[i].x]][bl[e[i].y]]=Mp[bl[e[i].y]][bl[e[i].x]]=i; add(bl[e[i].x],bl[e[i].y]); } memset(sze,0,sizeof(sze)); memset(son,0,sizeof(son)); dfs(1,0); Dfs(1,1); pre_calc(); k=rd(); for(int i=1;i<=k;i++) { int op=rd(), x=rd(), y=rd(); if(op==1) change(x,y); else { int l=lca(bl[x],bl[y]), ans=inf; ans=min(ans,min(ask_tree(bl[x],l),ask_tree(bl[y],l))); pii tx=ask_cir(x,l), ty=ask_cir(y,l); ans=min(ans,min(tx.first,ty.first)); ans=min(ans,calc(tx.second,ty.second)); printf("%d\n",ans); } } }