BZOJ2594 [Wc2006]水管局长数据加强版
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:BZOJ2594
正解:LCT
解题报告:
这道题需要维护动态删边,每次查询两点间的最大边权的最小值。
显然用LCT维护最小生成时即可,由于是删边,我们转化为倒着加边就可以了,就跟上一道题:魔法森林几乎一模一样了。
注意这题卡常,对于边的话,可以先sort一遍,依次往里面加,相当于是做了一遍最小生成树,常数小很多。
//It is made by ljh2000 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> using namespace std; typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); const int MAXN = 1100011; const int MAXM = 1000011; int n,m,Q,F[100011],father[MAXN],tr[MAXN][2],mx[MAXN],from[MAXN],tiao; int tot,tag[MAXN],top,stack[MAXN],a[MAXN],pos,match[MAXN][2],ans[100011]; bool stop[MAXM]; struct edge{ int x,y,z; }e[MAXM],lin; inline bool cmpw(edge TA,edge TAT){ return TA.z<TAT.z; } struct ask{ int type,x,y,bel; }q[100011]; struct node{ int x,id; }tmp; inline bool cmp(node TA,node TAT){ return TA.x<TAT.x; } vector<node>E[100011]; inline bool isroot(int x){ return (tr[father[x]][0]!=x) && (tr[father[x]][1]!=x); } inline int find(int x){ if(F[x]!=x) F[x]=find(F[x]); return F[x]; } inline void upd(int x,int y){ if(mx[x]<mx[y]) { mx[x]=mx[y]; from[x]=from[y]; } } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline int find_edge(int x,int y){ int l=0,r=E[x].size()-1,mid; while(l<=r) { mid=(l+r)>>1; if(E[x][mid].x==y) return E[x][mid].id; if(E[x][mid].x>y) r=mid-1; else l=mid+1; } return 0; } inline void update(int x){ from[x]=x; mx[x]=a[x]; int l=tr[x][0],r=tr[x][1]; if(l) upd(x,l); if(r) upd(x,r); } inline void pushdown(int x){ if(tag[x]==0) return ; int l=tr[x][0],r=tr[x][1]; tag[x]=0; tag[l]^=1; tag[r]^=1; swap(tr[x][0],tr[x][1]); } inline void rotate(int x){ int y,z; y=father[x]; z=father[y]; int l,r; l=(tr[y][1]==x); r=l^1; if(!isroot(y)) tr[z][(tr[z][1]==y)]=x; father[x]=z; father[y]=x; tr[y][l]=tr[x][r]; father[tr[x][r]]=y; tr[x][r]=y; update(y); update(x); } inline void splay(int x){ top=0; stack[++top]=x; int y,z; for(int i=x;!isroot(i);i=father[i]) stack[++top]=father[i]; for(int i=top;i>=1;i--) pushdown(stack[i]); while(!isroot(x)) { y=father[x]; z=father[y]; if(!isroot(y)) { if((tr[y][0]==x) ^ (tr[z][0]==y)) rotate(x); else rotate(y); } rotate(x); } } inline void access(int x){ int last=0; while(x) { splay(x); tr[x][1]=last; update(x);//!!! last=x; x=father[x]; } } inline void move_to_the_root(int x){ access(x); splay(x); tag[x]^=1; } inline void link(int x,int y){ move_to_the_root(x); father[x]=y; //splay(x); } inline void cut(int x,int y){ move_to_the_root(x); access(y); splay(y); tr[y][0]=father[x]=0; update(y); } inline void build(edge bian){ tot++; a[tot]=bian.z; from[tot]=tot; mx[tot]=a[tot]; match[tot][0]=bian.x; match[tot][1]=bian.y; link(bian.x,tot); link(bian.y,tot); } inline int query(int x,int y){ move_to_the_root(x); access(y); splay(y); pos=from[y]; return mx[y]; } inline void work(){ n=getint(); m=getint(); Q=getint(); tot=n; int now,bel; for(int i=1;i<=n;i++) F[i]=i; for(int i=1;i<=m;i++) { e[i].x=getint(); e[i].y=getint(); e[i].z=getint(); if(e[i].x>e[i].y) swap(e[i].x,e[i].y); } sort(e+1,e+m+1,cmpw); for(int i=1;i<=m;i++) { tmp.x=e[i].y; tmp.id=i; E[e[i].x].push_back(tmp); } for(int i=1;i<=n;i++) if(E[i].size()>0) sort(E[i].begin(),E[i].end(),cmp); for(int i=1;i<=Q;i++) { q[i].type=getint(); q[i].x=getint(); q[i].y=getint(); if(q[i].x>q[i].y) swap(q[i].x,q[i].y); if(q[i].type==2) q[i].bel=find_edge(q[i].x,q[i].y),stop[q[i].bel]=1; } for(int i=1;i<=m;i++) { if(stop[i]) continue; if(find(e[i].x)!=find(e[i].y)) { build(e[i]); F[find(e[i].x)]=find(e[i].y); continue; } //now=query(e[i].x,e[i].y); //if(now<=e[i].z) continue; //cut(pos,match[pos][0]); //cut(pos,match[pos][1]); //build(e[i]); } for(int o=Q;o>=1;o--) { if(q[o].type==1) { ans[o]=query(q[o].x,q[o].y); continue; } if(find(q[o].x)!=find(q[o].y)) { now=find_edge(q[o].x,q[o].y); build(e[now]); F[find(e[now].x)]=find(e[now].y); continue; } bel=q[o].bel; now=query(q[o].x,q[o].y); if(now<=e[bel].z) continue; cut(pos,match[pos][0]); cut(pos,match[pos][1]); build(e[bel]); } for(int i=1;i<=Q;i++) if(q[i].type==1) printf("%d\n",ans[i]); } int main() { work(); return 0; }
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!