BZOJ 1455: 罗马游戏 左偏树 or pb_ds
来源:互联网 发布:淘宝易轩数码靠谱吗 编辑:程序博客网 时间:2024/04/28 02:32
这道题看到支持合并操作就知道是启发式合并,就去学了一下左偏树,左偏树,顾名思义就是树是向左偏的,实质上是一个堆,我们只需对一个节点维护一个权值,这个权值等于其右儿子的权值加一,一旦发现左儿子的该权值比右儿子小就交换左右儿子,这样就能保证树的左偏性,当合并两颗左偏树的时候,我们先找出根节点权值较小的一个,然后将另一个插入到其右节点即可,并在回溯的过程中维护一下左偏性,这个过程虽然看起来比较麻烦,但是实际上的代码只需要一个简短的递归即可,下面附上这道题左偏树的代码
#include<cstdio>#include<cstdlib>#include<iostream>#include<iomanip>#include<ctime>#include<cmath>#include<cstring>#include<string>#include<algorithm>using namespace std;struct left_tree{ left_tree *ls,*rs; int key,h,pos; left_tree(int _,int __);}*null=new left_tree(0,0),*tree[1000001];left_tree :: left_tree(int _,int __){ key=_,pos=__; ls=rs=null; h=null?0:-1;}left_tree* my_merge(left_tree *x,left_tree *y){ if(x==null) return y; if(y==null) return x; if(x->key>y->key) swap(x,y); x->rs=my_merge(x->rs,y); if(x->ls->h<x->rs->h) swap(x->ls,x->rs); x->h=x->rs->h+1; return x;}int f[1000001];int find_fa(int x){ if(!f[x] || f[x]==x) return f[x]=x; else return f[x]=find_fa(f[x]);}bool dead[1000001];int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); tree[i]=new left_tree(x,i); } int m; scanf("%d",&m); for(int i=1;i<=m;i++) { char s[5]; scanf("%s",s); if(s[0]=='M') { int x,y; scanf("%d%d",&x,&y); if(dead[x] || dead[y]) continue; int o=find_fa(x); int p=find_fa(y); if(o!=p) { f[o]=p; tree[p]=my_merge(tree[o],tree[p]); } } else { int x; scanf("%d",&x); if(dead[x]) printf("0\n"); else { int o=find_fa(x); dead[tree[o]->pos]=true; printf("%d\n",tree[o]->key); tree[o]=my_merge(tree[o]->ls,tree[o]->rs); } } } return 0;}
另类题解:
不就是要支持合并的堆吗,找个能合并的STL不就行了吗,于是我们想到了STL pd_ds里的paring_heap,这样这道题在强大的pd_ds面前就变成了一道语法练习题。。。
#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>#include<algorithm>#include<iostream>#include<iomanip>#include<cstring>#include<string>#include<ext/pb_ds/priority_queue.hpp>using namespace std;struct point{ int num,v; bool operator < (point b) const{ return v>b.v; } point(int numm,int vv):num(numm),v(vv){}};__gnu_pbds::priority_queue<point> q[1000001];int f[1000001];int find_fa(int x){ if(x==f[x] || !f[x]) return f[x]=x; else return f[x]=find_fa(f[x]);}bool pd[1000001];char s[10];int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); q[i].push(point(i,x)); } int m; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s",s); if(s[0]=='M') { int l,r; scanf("%d%d",&l,&r); if(pd[l] || pd[r]) continue; int o=find_fa(l); int p=find_fa(r); if(o!=p) { f[o]=p; q[p].join(q[o]); } } if(s[0]=='K') { int x; scanf("%d",&x); if(pd[x]) printf("0\n"); else { int o=find_fa(x); pd[q[o].top().num]=true; printf("%d\n",q[o].top().v); q[o].pop(); } } } return 0;}
0 0
- BZOJ 1455: 罗马游戏 左偏树 or pb_ds
- BZOJ 1455 罗马游戏 左偏树
- bzoj 1455: 罗马游戏 左偏树
- 【BZOJ】1455 罗马游戏 左偏树
- BZOJ 1455 罗马游戏
- BZOJ 1455 罗马游戏
- bzoj 1455 罗马游戏
- bzoj 1455: 罗马游戏 左偏树入门
- BZOJ 1455: 罗马游戏 左偏树裸题
- BZOJ 1455 罗马游戏 [右偏树(误)][左偏树]
- 1455: 罗马游戏 左偏树
- 1455: 罗马游戏|左偏树
- BZOJ 1455 罗马游戏 可并堆
- BZOJ 1455: 罗马游戏 可并堆
- bzoj 1455 罗马游戏 解题报告
- BZOJ[1455]罗马游戏 可并堆
- bzoj 1455 && tyvj 2349 罗马游戏
- BZOJ 1455 罗马游戏 可并堆裸
- Mechanize模拟浏览器
- [玲珑杯#Round5]Grid Point 拉格朗日插值
- 华为机试在线训练-牛客网(4)质数因子
- 开发unity插件——一次搞定unity编辑器常用功能
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- BZOJ 1455: 罗马游戏 左偏树 or pb_ds
- VS Code折腾记 - (3) 多图解VSCode基础功能
- Linux下的网络环境配置
- 问题 B: 加油站(贪心+模拟)
- JZOJ4957. 【WC模拟】B君的宴请
- 别人家的 Toast——Toasty
- 01.19读写三行文件编译
- Mysql单文件存储删除数据Bug文件容量不会减少
- cross tool制作交叉编译工具链,编译binutils error