POJ 3481
HDU 5877
BZOJ 1208
BZOJ 3224 Tyvj 1728
BZOJ 1588
这些题目都很裸,套套模板就能A,所以就放一起了,treap=tree+heap,让数值维持二叉树性质,用随机值维护堆性质(用这个维护树的平衡)
const int N = 100010;
struct Treap{
int l,r; //左,右
int val,dat; //价值,随机值
int cnt,sz; //副本数,子树大小
}t[N];
int tot,root,n,INF = 0x7fffffff;
void init(){tot=0;}
int New(int val){t[++tot].val=val;t[tot].dat=rand();t[tot].l=t[tot].r=0;t[tot].cnt=t[tot].sz=1;return tot;}
void update(int p){t[p].sz=t[t[p].l].sz+t[t[p].r].sz+t[p].cnt;}
void build(){New(-INF); New(INF);root=1,t[1].r=2;update(root);}
void zig(int &p){int q=t[p].l;t[p].l=t[q].r,t[q].r=p,p=q;update(t[p].r),update(p);}
void zag(int &p){int q=t[p].r;t[p].r=t[q].l,t[q].l=p,p=q;update(t[p].l),update(p);}
void Insert(int &p,int val){ //插入
if(p==0){
p=New(val);
return ;
}
if(val==t[p].val){
t[p].cnt++,update(p);
return ;
}
if(val<t[p].val){
Insert(t[p].l,val);
if(t[p].dat<t[t[p].l].dat) zig(p);
}
else{
Insert(t[p].r,val);
if(t[p].dat<t[t[p].r].dat) zag(p);
}
update(p);
}
void Remove(int &p,int val){ //删除
if(p==0) return ;
if(val==t[p].val){
if(t[p].cnt>1){
t[p].cnt--,update(p);
return ;
}
if(t[p].l||t[p].r){
if(t[p].r==0||t[t[p].l].dat>t[t[p].r].dat)
zig(p),Remove(t[p].r,val);
else zag(p),Remove(t[p].l,val);
update(p);
}
else p=0;
return ;
}
val<t[p].val?Remove(t[p].l,val):Remove(t[p].r,val);
update(p);
}
int GetRankByVal(int p,int val){ //排名(记得减1,因为有-inf)
if(p==0) return 0;
if(val==t[p].val) return t[t[p].l].sz+1;//注意这个地方
if(val<t[p].val) return GetRankByVal(t[p].l,val);
return GetRankByVal(t[p].r,val)+t[t[p].l].sz+t[p].cnt;
}
int GetValByRank(int p,int rnk){ //排名为rnk的数(rnk记得加1,因为有-inf)
if(p==0) return INF;
if(t[t[p].l].sz>=rnk) return GetValByRank(t[p].l,rnk);
if(t[t[p].l].sz+t[p].cnt>=rnk) return t[p].val;
return GetValByRank(t[p].r,rnk-t[t[p].l].sz-t[p].cnt);
}
int GetPre(int val){ //前驱
int ans=1;
int p=root;
while(p){
if(val==t[p].val){
if(t[p].l>0){
p=t[p].l;
while(t[p].r>0) p=t[p].r;
ans=p;
}
break;
}
if(t[p].val<val&&t[p].val>t[ans].val) ans=p;
p=val<t[p].val?t[p].l:t[p].r;
}
return t[ans].val;
}
int GetNext(int val){ //后继
int ans=2;
int p=root;
while(p){
if(val==t[p].val){
if(t[p].r>0){
p=t[p].r;
while(t[p].l>0) p=t[p].l;
ans=p;
}
break;
}
if(t[p].val>val&&t[p].val<t[ans].val) ans=p;
p=val<t[p].val?t[p].l:t[p].r;
}
return t[ans].val;
}