您的位置:首页 > 其它

poj2761(treap入门)

2015-10-11 18:13 337 查看
给n个数,然后m个询问,询问任意区间的第k小的数,特别的,任意两个区间不存在包含关系,

也就是说,将所有的询问按L排序之后, 对于i<j , Li < Lj 且 Ri < Rj

所以只要每次查询的时候,treap都是对应区间[Li,Ri] ,那么查找第k小就很简单了

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <algorithm>
using namespace std;
const int INF = 1<<30;
const int N = 100001 + 10;
struct Treap
{
int ch[2];
int fix,key;
int same,cnt;
}treap[N*40];
struct Node
{
int l, r,k,id;
bool operator<(const Node&rhs)const
{
return l < rhs.l;
}
}q[N*5];
int tot;
int val
;
int ans[N*5];
void maintain(int o)
{
int lCnt = treap[o].ch[0] == 0 ? 0 : treap[treap[o].ch[0]].cnt;
int rCnt = treap[o].ch[1] == 0 ? 0 : treap[treap[o].ch[1]].cnt;
treap[o].cnt = treap[o].same + lCnt + rCnt;
}
void rotate(int &o, int d)
{
int t = treap[o].ch[d^1];
treap[o].ch[d^1] = treap[t].ch[d];
treap[t].ch[d] = o;
maintain(o);
maintain(t);
o = t;
}
void insert(int &o, int tkey)
{
if(o==0)
{
o = ++tot;
if(tot>=N*60) while(true);;
treap[o].ch[0] = treap[o].ch[1] = 0;
treap[o].cnt = treap[o].same = 1;
treap[o].key = tkey;
treap[o].fix = rand();
maintain(o);
}
else if(tkey < treap[o].key)
{
insert(treap[o].ch[0],tkey);
maintain(o);
if(treap[treap[o].ch[0]].fix > treap[o].fix)
rotate(o,1);
}
else if(tkey > treap[o].key)
{
insert(treap[o].ch[1],tkey);
maintain(o);
if(treap[treap[o].ch[1]].fix > treap[o].fix)
rotate(o,0);
}
else
{
treap[o].same++;
maintain(o);
}

}
void remove(int &o, int tkey)
{
if(tkey < treap[o].key)
{
remove(treap[o].ch[0],tkey);
}
else if(tkey > treap[o].key)
{
remove(treap[o].ch[1],tkey);
}
else
{
if(treap[o].same!=1)
treap[o].same--;
else if(treap[o].ch[0]==0 && treap[o].ch[1]==0)
o = 0;
else if(treap[o].ch[0]==0)
{
rotate(o,0);
remove(treap[o].ch[0],tkey);
}
else if(treap[o].ch[1]==0)
{
rotate(o,1);
remove(treap[o].ch[1],tkey);
}
else if(treap[treap[o].ch[0]].fix <= treap[treap[o].ch[1]].fix)
{
rotate(o,0);
remove(treap[o].ch[0],tkey);
}
else
{
rotate(o,1);
remove(treap[o].ch[1],tkey);
}
}
maintain(o);
}

int query(int o, int k)
{
while(o)
{
int cnt = treap[o].ch[0]==0 ? 0 : treap[treap[o].ch[0]].cnt;
if(cnt>=k)
o = treap[o].ch[0];
else if(cnt<k && k<=cnt+treap[o].same)
return treap[o].key;
else
{

k -= cnt + treap[o].same;
o = treap[o].ch[1];
}
}
}
int main()
{
//freopen("d:/in.txt","r",stdin);
int n,m;
srand(time(0));
while(scanf("%d%d",&n,&m)!=EOF)
{

for(int i=1;i<=n;++i)
{
scanf("%d",&val[i]);
}
tot = 0;
for(int i=0;i<m;++i)
{
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
q[i].id = i;
}
sort(q,q+m);
int root = 0;
int L=1,R=1;//初始在Treap中的节点所属区间[L,R),注意半闭半开区间
for(int i=0;i<m;i++)
{
while(L<q[i].l)
{
if(L<R) remove(root,val[L]);
L++;
}
if(R<L) R=L;
while(R<=q[i].r)
{
insert(root,val[R]);
R++;
}
ans[q[i].id]=query(root,q[i].k);
}
for(int i=0;i<m;i++) printf("%d\n",ans[i]);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: