還是套板子直接求。
/****************************
* author:crazy_石頭
* date:2014/05/08
* time:313 ms
* algorithm:Treap-求區間第大數
* Pro:POJ 1442
***************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define INF 1<<29
#define eps 1e-8
#define A system("pause")
#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define ms(a,b) memset((a),(b),sizeof(a))
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define LL long long
#define mod 100000000
const int maxn=100000+5;
const int maxm=100+10;
struct Node
{
Node* ch[2];//定義左右子樹;
int r,v;//每個結點的隨機優先級及value;
int s;//結點總數;
Node(int v):v(v)
{
ch[0]=ch[1]=NULL;
r=rand();
s=1;
}
bool operator <(const Node& rhs)const
{
return rs;
if(ch[1]!=NULL) s+=ch[1]->s;
}
};
inline void rotate(Node* &o,int d)//d==0表示左旋,d==1表示右旋;
{
Node* k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
o->maintain();
k->maintain();
o=k;
}
inline void insert(Node* &o,int x)//先是普通插入,if(x_vv?0:1);//不要用cmp函數,可能會有相同結點;
insert(o->ch[d],x);//插入新結點,比較優先級進行旋轉;
if(o->ch[d]->r>o->r) rotate(o,d^1);
}
o->maintain();//維護結點o的信息;
}
inline void remove(Node* &o,int x)
{
int d=o->cmp(x);
if(d==-1)
{
Node* u=o;
if(o->ch[0]!=NULL && o->ch[1]!=NULL)
{
int d2=(o->ch[0]->r>o->ch[1]->r?1:0);
rotate(o,d2);
remove(o->ch[d2],x);
}
else
{
if(o->ch[0]==NULL) o=o->ch[1];
else o=o->ch[0];
delete u;
}
}
else
remove (o->ch[d],x);
if(o!=NULL) o->maintain();
}
//查找區間第k大數;
inline int kth(Node* o,int k)
{
if(o==NULL || k<=0 || k>o->s) return 0;
int s=(o->ch[0]==NULL? 0:o->ch[0]->s);
if(k==s+1) return o->v;
else if(k<=s) return kth(o->ch[0],k);
else return kth(o->ch[1],k-s-1);
}
int a[maxn],n,m;
int main()
{
Node* rt=NULL;
scanf("%d%d",&m,&n);
rep(i,1,m) scanf("%d",&a[i]);
int st=1,test;
rep(i,1,n)
{
scanf("%d",&test);
while(st<=test)
{
insert(rt,a[st]);
st++;
}
printf("%d\n",kth(rt,i));
}
return 0;
}