hdu 5493 Queue treap实现将元素快速插入到第i个位置

时间:2021-01-27 10:44:50

input

T 1<=T<=1000

n 1<=n<=100000

h1 k1

h2 k2

... ...

hn kn

1<=hi<=1e9   0<=ki<=n-1

sum(n)<=1e6

hi!=hj(i!=j)

output

hi指第i个人的身高,ki指这个人前面或者后面比他高的人数

Case #cas: 输出可能的最小序列,没有输出impossible

做法:将所有人按身高排序,从高到低插入数组中,则插入到第i个人时,数组里所有人都比他高,用treap实现,每个人有两个位置可以插入,每次插入到小的位置

 #include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
#define MAX 100000
#define LL long long
int cas=,T,first,a[MAX+][];
struct node
{
node*ch[];
int r,v,sz;
void maintain() { sz=(ch[]?ch[]->sz:)+(ch[]?ch[]->sz:)+; }
};
void rotate(node* &o,int d)
{
node*k=o->ch[d^];o->ch[d^]=k->ch[d];k->ch[d]=o;
o->maintain();k->maintain();o=k;
}
void insert(node* &o,int pos,int &x)
{
if(o==NULL)
{
o=new node();
o->ch[]=o->ch[]=NULL;
o->v=x;o->r=rand();
o->sz=;
return;
}
o->sz++; //易错,旋转时可能没旋转到该结点,导致没更新,所以在插入后要++
int d;
if(pos <= (o->ch[]?o->ch[]->sz:)) d=;
else { d=;pos -= (o->ch[]?o->ch[]->sz:)+; }
insert(o->ch[d],pos,x);
if(o->ch[d]->r > o->r) rotate(o,d^);
}
void read(node*u)
{
if(u==NULL) return;
read(u->ch[]);
printf(" %d",u->v);
read(u->ch[]);
delete u;
}
int cmp(const void*a,const void*b) { return *(int*)b-*(int*)a; }
int main()
{
//freopen("/home/user/桌面/in","r",stdin);
scanf("%d",&T);
int n;
while(T--)
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d%d",&a[i][],&a[i][]);
qsort(a+,n,sizeof(a[]),cmp);
int i;
node *root=NULL;
for(i=;i<=n;i++)
{
if(a[i][]>=i) break;
int pos=std::min(a[i][],i--a[i][]);
insert(root,pos,a[i][]);
}
printf("Case #%d:",cas++);
if(i<=n) { puts(" impossible");continue; }
read(root);
printf("\n");
}
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return ;
}