bzoj2594 [Wc2006]水管局长数据加强版 离线+LCT维护边权
LCT维护边权势把每条边都当成一个点赋予点权,原来的点当然也保留,如果求和点权赋为0,求max点权赋为-INF,如果都要求,那就弄两三个点权。
需要注意的是,LCT的link操作必须换根,如果不把x设为根而直接pre[x]=y的话,结果并不是连接x和y而是连接x的splay的根和y。在弹飞绵羊的题中之所以不用换根是因为x本来就是根。
#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1500100; const int INF=1e9+10; int getint() { char ch=getchar(); for(;ch>'9'||ch<'0';ch=getchar()); int tmp=0; for(;'0'<=ch&&ch<='9';ch=getchar()) tmp=tmp*10+int(ch)-48; return tmp; } int n,m,qn; struct Edge { int u,v,w; bool e; friend bool operator<(Edge A,Edge B) { return A.u==B.u?A.v<B.v:A.u<B.u; } };Edge e[maxn]; struct Query { int op,x,y; };Query q[maxn]; int pre[maxn],ch[maxn][2],rev[maxn]; struct Node { int w,id; friend bool operator<(Node A,Node B) { return A.w<B.w; } };Node val[maxn],Max[maxn]; int fa[maxn]; int u,v,w; int op,x,y; int ans[maxn],cnt; bool cmp(Edge A,Edge B) { return A.w<B.w; } int bin(int l,int r,int x,int y) { int res=l; while(l<=r){ int m=(l+r)>>1; if(e[m].u==x&&e[m].v==y) return m; if(x>e[m].u||(x==e[m].u&&y>e[m].v)) l=m+1; else r=m-1; } } int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } bool isroot(int x) { return ch[pre[x]][0]!=x&&ch[pre[x]][1]!=x; } void update_rev(int x) { if(!x) return; swap(ch[x][0],ch[x][1]); rev[x]^=1; } void up(int x) { Max[x]=max(val[x],max(Max[ch[x][0]],Max[ch[x][1]])); } void down(int x) { if(rev[x]){ update_rev(ch[x][0]); update_rev(ch[x][1]); rev[x]=0; } } void Pd(int x) { if(!isroot(x)) Pd(pre[x]); down(x); } void rot(int x,int kind) { int y=pre[x]; ch[y][kind^1]=ch[x][kind]; pre[ch[x][kind]]=y; if(!isroot(y)) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; up(y); } void splay(int x) { Pd(x); while(!isroot(x)){ if(isroot(pre[x])) rot(x,ch[pre[x]][0]==x); else{ int y=pre[x],z=pre[y]; int kind=ch[y][0]==x,one=0; if(ch[y][0]==x&&ch[z][0]==y) one=1; if(ch[y][1]==x&&ch[z][1]==y) one=1; if(one) rot(y,kind),rot(x,kind); else rot(x,kind),rot(x,kind^1); } } up(x); } int access(int x) { int t=0; while(x){ splay(x); ch[x][1]=t; t=x;x=pre[x]; up(t); } return t; } void makeroot(int x) { access(x); splay(x); update_rev(x); } void link(int x,int y) { makeroot(x); pre[x]=y; } void cut(int x,int y) { makeroot(x); access(y); splay(y); ch[y][0]=pre[x]=0; } Node query(int x,int y) { makeroot(x); access(y); splay(y); return Max[y]; } int main() { freopen("in.txt","r",stdin); while(~scanf("%d%d%d",&n,&m,&qn)){ REP(i,1,n) fa[i]=i; REP(i,1,m){ u=getint();v=getint();w=getint(); if(u>v) swap(u,v); e[i]={u,v,w,1}; } sort(e+1,e+m+1); REP(i,1,qn){ op=getint();x=getint();y=getint(); if(x>y) swap(x,y); q[i]={op,x,y}; if(op==2){ int k=bin(1,m,x,y); e[k].e=0; } } sort(e+1,e+m+1,cmp); REP(i,1,m){ if(e[i].e==0) continue; x=find(e[i].u),y=find(e[i].v); if(x==y) e[i].e=0; else fa[x]=y; } sort(e+1,e+m+1); REP(i,0,n+m) pre[i]=rev[i]=0,MS0(ch[i]),val[i]={-INF,i},Max[i]={-INF,i}; REP(i,1,m){ if(e[i].e==0) continue; x=e[i].u,y=e[i].v,w=e[i].w; val[n+i].w=Max[n+i].w=w; link(x,n+i); link(y,n+i); } Node tmp;int xx,yy;cnt=0; for(int i=qn;i>=1;i--){ op=q[i].op,x=q[i].x,y=q[i].y; tmp=query(x,y); if(op==1) ans[++cnt]=tmp.w; else{ int k=bin(1,m,x,y); if(e[k].w<tmp.w){ xx=e[tmp.id-n].u,yy=e[tmp.id-n].v; cut(tmp.id,xx); cut(tmp.id,yy); pre[n+k]=rev[n+k]=0;MS0(ch[n+k]); val[n+k]=Max[n+k]={e[k].w,n+k}; link(x,n+k); link(y,n+k); } } } for(int i=cnt;i>=1;i--) printf("%d\n",ans[i]); } return 0; }
没有AC不了的题,只有不努力的ACMER!