bzoj 2733 [HNOI2012]永无乡
来源:互联网 发布:拍拍贷淘宝买满标流程 编辑:程序博客网 时间:2024/06/05 11:23
传送门
Sol
- 一眼看上去是水题,没想到跪了一上午。。。
- 看到第k小想到平衡树,维护连通性用并查集。因此主要思路就是维护一个平衡树森林,合并操作就把两个平衡树合并
- 难点在于,合并暴力肯定TLE,因此需要启发式合并
void dfs(int p,int &f){ if(lc) dfs(lc,f); if(rc) dfs(rc,f); int x,y; split(f,val[p],x,y); renode(p); f=merge(merge(x,p),y);}
- 代码是fhq treap。虽然就是把一颗平衡树拆掉再一个一个加到另一颗树里。但是启发式合并的巧妙在于,它是把节点数小的树拆掉合并到大的树上,于是均摊复杂度就成了优雅的
O(nlogn) - 合并的时候还有一些细节:节点信息的清空和并查集的更新
Code
// by spli#include<cstring>#include<cstdio>#include<iostream>#include<algorithm>#include<ctime>#define lc ch[p][0]#define rc ch[p][1]using namespace std;const int N=100010*2;int n,m,q,sz;int c[N],pos[N];int lnk[N];int siz[N];int col[N],rt;int ch[N][2];int pri[N];int val[N];int _find(int x){ if(x!=lnk[x]) lnk[x]=_find(lnk[x]); return lnk[x];}int newnode(int id){ sz++; siz[sz]=1; val[sz]=c[id]; pos[sz]=id; pri[sz]=rand(); return sz;}void pushup(int p){ siz[p]=1; if(lc) siz[p]+=siz[lc]; if(rc) siz[p]+=siz[rc];}int merge(int x,int y){ if(!x||!y) return x+y; if(pri[x]<pri[y]){ ch[x][1]=merge(ch[x][1],y); pushup(x); return x; } else{ ch[y][0]=merge(x,ch[y][0]); pushup(y); return y; }}void split(int p,int v,int &x,int &y){ if(!p){ x=0,y=0; return; } if(val[p]<=v) x=p,split(rc,v,rc,y); else y=p,split(lc,v,x,lc); pushup(p);}int getmin(int p){ while(1){ if(lc) p=lc; else return val[p]; }}void renode(int p){ lc=rc=0;}void dfs(int p,int &f){ if(lc) dfs(lc,f); if(rc) dfs(rc,f); int x,y; split(f,val[p],x,y); renode(p); f=merge(merge(x,p),y);}void DFS(int p){ if(lc) DFS(lc); cout<<pos[p]<<" "; if(rc) DFS(rc);}void un(int x,int y){ int r[2]; r[0]=_find(x); r[1]=_find(y); if(r[0]==r[1]) return; if(siz[r[0]]<siz[r[1]]) swap(r[0],r[1]); dfs(r[1],r[0]); lnk[_find(x)]=lnk[_find(y)]=r[0]; lnk[r[0]]=r[0];}int get_th(int p,int k){ while(1){ if(k<=siz[lc]) p=lc; else if(k==siz[lc]+1) return p; else k-=siz[lc],k--,p=rc; }}void query(int a,int k){ int rt=_find(a); if(siz[rt]<k) puts("-1"); else printf("%d\n",pos[get_th(rt,k)]);}int main(){ srand(19260817); scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%d",&c[i]); //ins(i,c[i]); col[i]=newnode(i); } for(int i=1;i<=n;++i) lnk[i]=i; int a,b; while(m--) scanf("%d%d",&a,&b),un(a,b); scanf("%d",&q); int x,y,c,d; char op[10]; while(q--){ scanf("%s",op); scanf("%d%d",&x,&y); if(op[0]=='B') un(x,y); if(op[0]=='Q') query(x,y); } return 0;}
阅读全文
0 0
- [BZOJ 2733][HNOI2012]永无乡
- bzoj 2733: [HNOI2012]永无乡
- bzoj 2733: [HNOI2012]永无乡
- 【BZOJ 2733】 [HNOI2012]永无乡
- BZOJ 2733: [HNOI2012]永无乡
- bzoj 2733 [HNOI2012]永无乡
- bzoj 2733 [HNOI2012]永无乡
- bzoj 2733 [HNOI2012]永无乡
- BZOJ 2733 [HNOI2012] 永无乡 Treap
- BZOJ 2733 HNOI2012 永无乡 Treap+启发式合并
- 【BZOJ 2733】 [HNOI2012]永无乡|Splay启发式合并
- bzoj 2733 [HNOI2012]永无乡 splay启发式合并
- 【BZOJ 2733】[HNOI2012]永无乡 启发式合并treap
- BZOJ 2733: [HNOI2012]永无乡 (Treap+启发式合并)
- BZOJ 2733([HNOI2012]永无乡-Treap启发式合并)
- bzoj 2733【hnoi2012】永无乡(平衡树)
- BZOJ 2733 2733: [HNOI2012]永无乡 平衡树启发式合并
- 【并查集套可持久化线段树】【bzoj 2733】: [HNOI2012]永无乡
- 极大似然估计
- [大数据-linux基础]linux ssh远程连接出现IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
- angular4中日期格式的用法
- Oracle 创建 split 和 splitstr 函数
- 在Oracle中执行动态SQL的几种方法
- bzoj 2733 [HNOI2012]永无乡
- Java字符串转数字(不使用jdk工具方法)
- PE文件学习笔记(五):导入表、IAT、绑定导入表解析
- cpp引用的运用场景
- springmvc静态资源解析异常的问题
- Python selenium自动化识别验证码模拟登录操作(二)
- Promise在工作中常用的几种示例
- 使用ES6语法进行Base64的编码和解码
- Qt中路径问题小结