Double Queue

本打算学二叉树,单纯的二叉树感觉也就那几种遍历了, 无意中看到了这个题,然后就花了两天时间又去学了学Treap树,真的不好理解,真应该从基础开始的,但我比较倔强,看到这题一定要先做了再说。上午和某公众号交流了一下,初学,不明白为什么要借助随机优先值来修正,而这题本身自带优先值,为什么不能用这个来修正呢,给出的回答是:为了保证平衡,因为键值生成的BST树有很多种形态,需要另外一个key来保证二叉树的形态,而固定的函数在某些特殊情况下可能会不平衡,所以随机值比较靠谱。题目中所给的优先级不能保证树的形态,随机数辅助性的修正树的形态。还是有点不明白,先来个题解以后回过来应该更好理解了吧。

当然,这题典型用treap树做,但set、map、SBT、splay都可以的。下面给出Treap和set的方法,set这个相比要更简单,但treap有着set不可比拟的优势!

Treap

struct node
{
node *ch[2];
int r,k,p;
node(int kk,int pp)
{
r=rand();
k=kk,p=pp;
ch[0]=ch[1]=NULL;
}
int cmp(int x)
{
if(x==p) return -1;
return x<p?0:1;
}
};
int find(node *root,int d)
{
while(root->ch[d])
{
root=root->ch[d];
}
printf("%d\n",root->k);
return root->p;
}
void rotate(node *&root,int d)
{
node *tmp=root->ch[d^1];
root->ch[d^1]=tmp->ch[d];
tmp->ch[d]=root;
root=tmp;
}
void insert(node *&root,int k,int p)
{
if(root==NULL) root=new node(k,p);
else
{
int d=p < root->p?0:1;
insert(root->ch[d],k,p);
if(root->ch[d]->r > root->r)//破坏了树的形态
rotate(root,d^1);
}
}
void remove(node *&root,int v)
{
int d=root->cmp(v);
if(d==-1)
{
node *tmp=root;
if(root->ch[1]&&root->ch[0])
{
int d2=root->ch[1]->r < root->ch[0]->r?1:0;
rotate(root,d2);//哪边小就往哪边旋转
remove(root->ch[d2],v);
}
else
{
if(root->ch[0]==NULL) root=root->ch[1];
else root=root->ch[0];
delete tmp;//记得删除节点;
}
}
else remove(root->ch[d],v);
}
int main()
{
int n;
node *root=NULL;
while(~scanf("%d",&n)&&n)
{
if(n==1)
{
int k,p;
scanf("%d%d",&k,&p);
insert(root,k,p);
}
else
{
if(root==NULL) printf("0\n");
else
{
int d=(n==2)?1:0;
int v=find(root,d);
remove(root,v);
}
}
}
return 0;
}

set

struct p
{
int r,k;
bool operator <(const p& tmp)const//自定义优先级
{return r<tmp.r;}
};
set<p>q;
int main()
{
q.clear();
int n;
while(~scanf("%d",&n)&&n)
{
if(n==1)
{
int k,r;
scanf("%d%d",&k,&r);
p tmp=(p){r, k};
q.insert(tmp);
}
else
{
if(q.size()==0) printf("0\n");
else
{
set<p>::iterator it;
if(n==2) it=--q.end();
else it=q.begin();
printf("%d\n",it->k);
q.erase(it);
}
}
}
return 0;
}

边学边做,越学发现自己不会的越多,但至少自己是在进步,加油!

最新文章

  1. Xcode LLDB 调试Tips
  2. 100_1小记ressons analysis
  3. js面向对象的使用方法
  4. Android按钮的各个样式设置
  5. asp.net服务器控件onclick带参数
  6. [Oracle]配置path使oracle备份/导入数据命令exp/imp起作用
  7. Android 分析工具 APKAnalyser
  8. Entity Framework 6.1-Code First
  9. 【win8技巧】去掉Win8导航菜单下面的这台电脑其他的文件夹
  10. 10:Hello, World!的大小
  11. Number Sequence (HDoj1005)
  12. Java虚拟机体系结构
  13. Unity学习笔记(二)——第一个Unity项目Hello Unity
  14. MediaWiki搭建教程
  15. 【JavaScript_轮播图】
  16. Python 文件读写的三种模式和区别
  17. 用PRODUCT_COPY_FILES拷贝文件夹
  18. Web压力测试工具 LoadRunner12.x简易入门教程--(一)回放与录制
  19. UVA 818 Cutting Chains(状压 + 暴搜)题解
  20. mpvue上手教程

热门文章

  1. List 集合中数据不重复的使用
  2. RK3288开发过程中遇到的问题点和解决方法之Devices
  3. uvm_config_db——半个全局变量
  4. POJ 2955 Brackets (区间DP,常规)
  5. codevs 1390 回文平方数 USACO
  6. htmlunit抓取js执行后的网页源码
  7. readystatechange
  8. Linux系统分区 进程管理 软件包安装
  9. Codeforces Round #272 (Div. 2)-A. Dreamoon and Stairs
  10. Difference between x:Reference and x:Name