【bzoj2594】[Wc2006]水管局长数据加强版 link cut tree
2016-01-04 21:03
411 查看
好久的坑了,今天终于填上了。
一直想总结一下LCT,结果发现难题都不会做。
离线处理,因为删边比较难做,所以我们倒着做变成加边操作。
问题转化成加边维护最小生成树,用lct维护一下最大的边是哪一条,一旦新加入的边形成环了,那么看一看环上最大的边和新加入的边哪个大,如果新加入的边小,那么删除原来的边,加入这一条边。
竟然1A,简直不可思议,不过时间慢成狗。
一直想总结一下LCT,结果发现难题都不会做。
离线处理,因为删边比较难做,所以我们倒着做变成加边操作。
问题转化成加边维护最小生成树,用lct维护一下最大的边是哪一条,一旦新加入的边形成环了,那么看一看环上最大的边和新加入的边哪个大,如果新加入的边小,那么删除原来的边,加入这一条边。
竟然1A,简直不可思议,不过时间慢成狗。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #define maxn 1500010 using namespace std; struct yts { int x,y,id,z; int tag; }e[1000010]; struct yts1 { int op,x,y,ans,id; }q[100010]; int fa[maxn],ch[maxn][2],val[maxn],mx[maxn]; bool rev[maxn]; int f[100010]; int n,m,T,tot,num; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } bool cmp1(yts x,yts y) { return x.x<y.x || (x.x==y.x && x.y<y.y); } int find(int x,int y) { int l=1,r=m,ans; while (l<=r) { int mid=(l+r)/2; if (e[mid].x==x && e[mid].y==y) return mid; if (e[mid].x<x || (e[mid].x==x && e[mid].y<y)) ans=mid,l=mid+1; else r=mid-1; } return ans; } bool cmp2(yts x,yts y) { return x.z<y.z; } bool cmp3(yts x,yts y) { return x.id<y.id; } int dir(int x) { return x==ch[fa[x]][1]; } int isroot(int x) { return !(x==ch[fa[x]][0] || x==ch[fa[x]][1]); } void push_up(int x) { mx[x]=x; if (val[mx[ch[x][0]]]>val[mx[x]]) mx[x]=mx[ch[x][0]]; if (val[mx[ch[x][1]]]>val[mx[x]]) mx[x]=mx[ch[x][1]]; } void reverse(int x) { rev[x]^=1; swap(ch[x][0],ch[x][1]); } void push_down(int x) { if (rev[x]) { if (ch[x][0]) reverse(ch[x][0]); if (ch[x][1]) reverse(ch[x][1]); rev[x]^=1; } } void rotate(int x) { int y=fa[x],z=fa[y],b=dir(x),a=ch[x][!b],c=dir(y); if (!isroot(y)) ch[z][c]=x; fa[x]=z;fa[y]=x;ch[x][!b]=y;ch[y][b]=a; if (a) fa[a]=y; push_up(y);push_up(x); } void down(int x) { if (!isroot(x)) down(fa[x]); push_down(x); } void splay(int x) { down(x); while (!isroot(x)) { int y=fa[x]; if (isroot(y)) rotate(x); else { int b=dir(x),c=dir(y); if (b^c) { rotate(x);rotate(x); } else { rotate(y);rotate(x); } } } } void access(int x) { for (int y=0;x;y=x,x=fa[x]) { splay(x); ch[x][1]=y; push_up(x); } } void make_root(int x) { access(x); splay(x); reverse(x); } void cut(int x,int y) { make_root(x); access(x); splay(y); fa[y]=0; } void link(int x,int y) { make_root(x); fa[x]=y; } int query(int x,int y) { make_root(x); access(y); splay(y); return mx[y]; } int find(int x) { if (f[x]==x) return x; else return f[x]=find(f[x]); } int main() { n=read();m=read();T=read(); for (int i=1;i<=m;i++) {e[i].x=read();e[i].y=read();e[i].z=read();if (e[i].x>e[i].y) swap(e[i].x,e[i].y);} sort(e+1,e+m+1,cmp2); for (int i=1;i<=m;i++) {e[i].id=i;val[i+n]=e[i].z;mx[i+n]=i+n;} sort(e+1,e+m+1,cmp1); for (int i=1;i<=T;i++) { q[i].op=read();q[i].x=read();q[i].y=read(); if (q[i].x>q[i].y) swap(q[i].x,q[i].y); if (q[i].op==2) { int x=find(q[i].x,q[i].y); q[i].id=e[x].id; e[x].tag=1; } } sort(e+1,e+m+1,cmp3); for (int i=1;i<=n;i++) f[i]=i; for (int i=1;i<=m;i++) if (!e[i].tag) { int f1=find(e[i].x),f2=find(e[i].y); if (f1!=f2) { num++; link(e[i].x,i+n);link(e[i].y,i+n); f[f1]=f2; if (num==n-1) break; } } for (int i=T;i>=1;i--) { if (q[i].op==1) q[i].ans=val[query(q[i].x,q[i].y)]; else { int x=query(q[i].x,q[i].y); if (e[q[i].id].z<val[x]) cut(e[x-n].x,x),cut(e[x-n].y,x),link(q[i].x,q[i].id+n),link(q[i].y,q[i].id+n); } } for (int i=1;i<=T;i++) if (q[i].op==1) printf("%d\n",q[i].ans); return 0; }
相关文章推荐
- 第五章(使用对象) 编程题一
- mfc的定时器函数
- netty4源码解读
- LeetCode Letter Combinations of a Phone Number
- 关系型数据库管理系统简介
- 把重载的那些消息都看看,熟悉一下功能
- Synchronized原理
- python 代码片段19
- 【ThinkPHP3.2.3】学习ThinkPHP笔记:搭建环境(1)
- unity的TRANSFORM_TEX详解
- 以梦为马
- Mac 使用技巧
- ios之修饰符(public、internal、private)
- cocos2d-x3.2下使用Umeng 64位SDK注意事项
- UIViewController控制器的生命周期
- mfc的 windows消息处理
- js常见问题之为什么点击弹出的i总是最后一个
- 判断JavaScript对象为null或者属性为空的方法
- 文本框控件字体,背景色都可以单独设置。
- linux shell if语句