Treap(Tree+Heap)---是一種通過 rand() 來隨機生成數字作爲修正值來調整的平衡樹。
基本操作:
1.旋轉。
2.插入(合併重複的),刪除(懶惰刪除)。
3.查最值,求第k小,求排名。
4.中序遍歷就是從小到大的。
5.維護附加關鍵字.
1.求第k小:
POJ1442
//12321199 1442 Accepted 976K 204MS C++ 2080B 2013-11-22 20:33:35靜態
//12321216 1442 Accepted 1804K 329MS C++ 2125B 2013-11-22 20:39:40動態
#include <iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cstdlib>
using namespace std;
#define MAX 30005
int a[MAX];
int u[MAX];
int tot;
class Node
{
public:
int vol,fix;
int size;
Node *left;
Node *right;
int lsize(){return left?left->size:0;}
int rsize(){return right?right->size:0;}
}*root;//space[MAX]
void left_rotate(Node *&a)
{
Node *b=a->right;
a->right=b->left;
b->left=a;
a=b;
b=a->left;
b->size=b->lsize()+b->rsize()+1;
a->size=a->lsize()+a->rsize()+1;
}
void right_rotate(Node *&a)
{
Node *b=a->left;
a->left=b->right;
b->right=a;
a=b;
b=a->right;
b->size=b->lsize()+b->rsize()+1;
a->size=a->lsize()+a->rsize()+1;
}
void insert(Node*&p,int vol)
{
if(!p)
{
p=new Node();
//p=&space[tot++]; //靜態
p->fix=rand();
p->vol=vol;
p->size=1;
}
else if(vol<=p->vol)
{
insert(p->left,vol);
p->size++;
if(p->left->fix < p->fix)
right_rotate(p);
}
else
{
insert(p->right,vol);
p->size++;
if(p->right->fix < p->fix)
left_rotate(p);
}
}
int get_kth(Node *&p,int k)
{
int key=p->lsize()+1;
if(k < key)
return get_kth(p->left,k);
else if(k > key)
return get_kth(p->right,k-key);
else
return p->vol;
}
void init()
{
root=NULL;
//memset(space,0,sizeof(space));靜態
//tot=1;
}
int main()
{
srand(time(0));
int n,m;
while(~scanf("%d%d",&m,&n))
{
for(int i=1;i<=m;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&u[i]);
int j=1;
init();
for(int i=1;i<=m;i++)
{
insert(root,a[i]);
while(j<=n&&i==u[j])
{
printf("%d\n",get_kth(root,j));
j++;
}
if(j>n) break;
}
}
return 0;
}
2.動態求最值
//12321728 3481 Accepted 212K 282MS C++ 1857B 2013-11-22 22:26:19動態
#include <iostream>
#include<cstdlib>
#include<ctime>
#include<cstdio>
#include<cstring>
using namespace std;
//#define MAX 10000005
class Node
{
public:
int vol,fix,cus;
Node* left;
Node* right;
}*root;//,space[MAX]
int tot=1;
void r_rotate(Node*&a)
{
Node*b=a->left;
a->left=b->right;
b->right=a;
a=b;
b=a->right;
}
void l_rotate(Node*&a)
{
Node*b=a->right;
a->right=b->left;
b->left=a;
a=b;
b=a->left;
}
void insert(Node*&p,int cus,int vol)
{
if(!p)
{
p=new Node();
//p=&space[tot++];
p->fix=rand();
p->vol=vol;
p->cus=cus;
}
else if(p->vol >= vol)
{
insert(p->left,cus,vol);
if(p->left->fix < p->fix)
r_rotate(p);
}
else
{
insert(p->right,cus,vol);
if(p->right->fix < p->fix)
l_rotate(p);
}
}
int Min(Node*&p)
{
if(!p)return 0;
if(!p->left)
{
Node*t=p;
int ans=p->cus;
p=p->right;
delete t;
return ans;
}
else return Min(p->left);
}
int Max(Node*&p)
{
if(!p)return 0;
if(!p->right)
{
Node*t=p;
int ans=p->cus;
p=p->left;
delete t;
return ans;
}
else return Max(p->right);
}
int main()
{
srand(time(0));
int a;
while(~scanf("%d",&a)&&a)
{
if(a==1)
{
int b,c;
scanf("%d%d",&b,&c);
insert(root,b,c);
}
else if(a==3)
{
printf("%d\n",Min(root));
}
else
{
printf("%d\n",Max(root));
}
}
return 0;
}
3.區間第k小:
//12329808 2761 Accepted 3500K 1844MS C++ 3889B 2013-11-25 21:28:45靜態
//12329836 2761 Accepted 3900K 3922MS C++ 3962B 2013-11-25 21:34:10動態
#include <iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAX 2000005
int dog[MAX];
int ans[MAX];
class Interval
{
public:
int s,e,k;
int id;
bool operator<(const Interval a) const
{
return s<a.s;
}
}qu[MAX];
class Node
{
public:
int vol,fix,size;
Node*left;
Node*right;
int lsize(){return left?left->size:0;}
int rsize(){return right?right->size:0;}
}*root,space[MAX];
int tot;
void r_rotate(Node*&a)
{
Node*b=a->left;
a->left=b->right;
b->right=a;
a=b;
b=a->right;
b->size=b->lsize()+b->rsize()+1;/**RE在這裏,不要把求size順序搞反了*/
a->size=a->lsize()+a->rsize()+1;
}
void l_rotate(Node*&a)
{
Node*b=a->right;
a->right=b->left;
b->left=a;
a=b;
b=a->left;
b->size=b->lsize()+b->rsize()+1;
a->size=a->lsize()+a->rsize()+1;
}
void insert(Node*&p,int vol)
{
if(!p)
{
p=&space[tot++];
//p=new Node();
p->left=NULL;
p->right=NULL;
p->fix=rand();
p->vol=vol;
p->size=1;
}
else if(p->vol > vol)
{
p->size++;
insert(p->left,vol);
if(p->left->fix < p->fix)
r_rotate(p);
}
else
{
p->size++;
insert(p->right,vol);
if(p->right->fix < p->fix)
l_rotate(p);
}
}
void del(Node*&p,int key)
{
if(!p) return ;
p->size--; /**注意size的減減**/
if(key==p->vol)
{
if(!p->left || !p->right)
{
//Node *t=p;
if(!p->left)
p=p->right;
else
p=p->left;
//delete t;
}
else
{
if(p->right->fix < p->left->fix)
{
l_rotate(p);
p->size--;/**注意size的減減**/
del(p->left,key);
}
else
{
r_rotate(p);
p->size--;/**注意size的減減**/
del(p->right,key);
}
}
}
else if(key < p->vol)
del(p->left,key);
else
del(p->right,key);
}
int find_kth(Node*&p,int k)
{
int sum=p->lsize()+1;
if(k < sum)
{
return find_kth(p->left,k);
}
else if(k>sum)
{
return find_kth(p->right,k-sum);
}
else
{
return p->vol;
}
}
int solve(Interval t1,Interval t2)
{
for(int i=t1.s;i<=min(t2.s-1,t1.e);i++)
del(root,dog[i]);
if(t1.e > t2.e)
{
for(int i=t2.e+1;i<=t1.e;i++)
del(root,dog[i]);
}
for(int i=max(t1.e+1,t2.s);i<=t2.e;i++)
insert(root,dog[i]);
return find_kth(root,t2.k);
}
int main()
{
srand(time(0));
//int T;
//scanf("%d",&T);
int n,m;
while(~scanf("%d%d",&n,&m))
{
root=NULL;
tot=1;
memset(space,NULL,sizeof(space));
for(int i=1;i<=n;i++)
scanf("%d",&dog[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&qu[i].s,&qu[i].e,&qu[i].k);
if(qu[i].s > qu[i].e) swap(qu[i].s,qu[i].e);
qu[i].id=i;
}
sort(qu+1,qu+1+m);
for(int i=qu[1].s;i<=qu[1].e;i++)
insert(root,dog[i]);
ans[qu[1].id]=find_kth(root,qu[1].k);
for(int i=2;i<=m;i++)
{
ans[qu[i].id]=solve(qu[i-1],qu[i]);
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
return 0;
}