BZOJ 1455 罗马游戏 可并堆裸
2015-07-23 15:00
225 查看
题意:链接
方法:可并堆
解析:
来二中的第几天来着忘记了,讲了可并堆,于是去找裸题来刷。
对于合并操作,如果有一个为空则根为另一个。
然后我们不妨假设x键值小于y。
那么由于左偏树的左右子树同为左偏树,所以整个过程就形成了个递归
即把x的右子树再与y为根的子树合并。
合并后维护左偏,即保证NPL的左比右大。
之后再更新根节点的NPL。
其实以上就是合并的全过程,只是叙述一遍加深记忆而已。
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 1000010 using namespace std; int ch [2],h ,key ,fa ; bool col ; int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} int merge(int x,int y) { if(!x)return y; if(!y)return x; if(key[y]<key[x])swap(x,y); ch[x][1]=merge(ch[x][1],y); if(h[ch[x][1]]>h[ch[x][0]])swap(ch[x][0],ch[x][1]); if(!h[ch[x][1]])h[x]=0; else h[x]=h[ch[x][1]]+1; return x; } int n,q; char s[5]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&key[i]); for(int i=1;i<=n;i++)fa[i]=i; h[0]=-1; scanf("%d",&q); for(int i=1;i<=q;i++) { scanf("%s",s); if(s[0]=='M') { int x,y; scanf("%d%d",&x,&y); if(col[x]||col[y])continue; int fx=find(x),fy=find(y); if(fx!=fy) { int t=merge(fx,fy); fa[fx]=t,fa[fy]=t; } }else { int x; scanf("%d",&x); if(col[x])printf("%d\n",0); else { int fx=find(x); col[fx]=1; printf("%d\n",key[fx]); fa[fx]=merge(ch[fx][0],ch[fx][1]); fa[fa[fx]]=fa[fx]; } } } }
相关文章推荐
- 十五天精通WCF——第十三天 用WCF来玩Rest
- [Unity3D]Unity3D游戏开发3D选择场景中的对象,并显示轮廓效果强化版
- location.pathname;outline:medium;undefined不能加引号
- OracleBulkCopy的批量数据导入
- poj 2406 Power Strings【最小循环节】
- html中js取值
- UTF-8编码问题编码长度问题
- GRE写作必备句型
- [ASP.NET MVC 小牛之路]17 - 捆绑(Bundle)
- 异步复位同步释放
- 如何使用Ajax进行登录校验
- 在RedHat Linux 9.0下配置DNS服务器Bind 9.2.6
- MySQL数据导出与导入
- cuckoo数据库变更
- 利用ApnsPHP包向IOS推送消息
- JSON学习笔记
- 【Linux_Fedora_应用系列】_5_如何安装XZ Utils 解压缩工具以及利用 xz工具来解压缩.xz文件
- python-ConfigParser模块【读写配置文件】
- swift页面跳转动画
- 编程式事务管理