[BZOJ]2733永无乡 做题笔记
2016-02-17 17:28
344 查看
题目来源:http://www.lydsy.com/JudgeOnline/problem.php?id=2733
这题是Splay启发式合并。
启发式合并,感觉也像是一种暴力,把小的一堆拆开强行放到大的一堆里面。。
使用并查集来维护两个结点是否位于一颗子树上。
这题是Splay启发式合并。
启发式合并,感觉也像是一种暴力,把小的一堆拆开强行放到大的一堆里面。。
使用并查集来维护两个结点是否位于一颗子树上。
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; const int MAX=100009; struct Splay { int a[MAX],f[MAX],s[MAX],fa[MAX]; int ch[MAX][2]; int find (int x) { if (x==fa[x]) return x; fa[x]=find(fa[x]); return fa[x]; } void update (int x) { s[x]=s[ch[x][0]]+s[ch[x][1]]+1; } void rotate(int x) { int y=f[x],opt; if (ch[f[x]][0]==x) opt=0; else opt=1; ch[y][opt]=ch[x][!opt]; if (ch[x][!opt]) f[ch[x][!opt]]=y; f[x]=f[y]; if (f[y]) if (ch[f[y]][0]==y) ch[f[y]][0]=x; else ch[f[y]][1]=x; f[y]=x,ch[x][!opt]=y; update(y),update(x); } void splay (int x,int to=0) { while (f[x]!=to) { if (f[f[x]]==to) rotate(x); else if ((ch[f[f[x]]][0]==f[x])== (ch[f[x]][0]==x)) rotate(f[x]),rotate(x); else rotate(x),rotate(x); } } void insert (int x,int y) { while (1) { if (a[y]<=a[x]) { if (ch[x][0]) x=ch[x][0]; else { f[y]=x; ch[x][0]=y; break; } } else { if (ch[x][1]) x=ch[x][1]; else { f[y]=x; ch[x][1]=y; break; } } } update(x); splay(y); } void merge (int x,int y) { if (!y) return ; merge(x,ch[y][0]); merge(x,ch[y][1]); ch[y][0]=ch[y][1]=0;s[y]=1; insert(x,y); } void addedge (int x,int y) { int fx=find(x); int fy=find(y); if (fx!=fy) { fa[fy]=fx; splay(x);splay(y); if (s[x]<s[y]) swap(x,y); merge(x,y); } } int find_by_rank (int x,int k) { while (x) { if (s[ch[x][0]]+1==k) return x; if (k<s[ch[x][0]]+1) x=ch[x][0]; else k-=s[ch[x][0]]+1,x=ch[x][1]; } return 0; } void query (int x,int k) { splay(x); if (k>s[x]) { puts("-1");return ; } printf("%d\n",find_by_rank(x,k)); } }Sp; int n,m,q; int main () { int a,b; char ch; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d",&Sp.a[i]); Sp.fa[i]=i; Sp.s[i]=1; } for (int i=1;i<=m;i++) { scanf("%d%d",&a,&b); Sp.addedge(a,b); } scanf("%d",&q); for (int i=1;i<=q;i++) { while ((ch=getchar())!='Q'&&ch!='B'); if (ch=='Q') { scanf("%d%d",&a,&b); Sp.query(a,b); } else if (ch=='B') { scanf("%d%d",&a,&b); Sp.addedge(a,b); } } return 0; }
相关文章推荐
- 递归的一个例子
- xcode升级运行报错 Command /usr/bin/codesign failed with exit code 1(api打包出错)
- 设计模式小纪
- MyBatis代码自动生成
- JS入门之ActiveXObject对象
- ArcGIS制图——多图层道路压盖处理
- SOAP Handler
- des,d2des,d3des的区别
- 利用css的before和after属性,实现类似QQ对话框效果
- java中的不同进制
- Android中ExpandableListView的使用 (一)
- flask入门学习(一)
- ORA-1652: unable to extend temp segment
- the error code is 2203
- 一、开发环境搭建及配置
- Linux常用命令
- HTTP协议之Content-Encoding
- VS2013 OpenCV 3.1环境搭建
- [ACM] 常数和语言基础
- 基于TINY4412的Andorid开发-------简单的LED灯控制