直接上题解
学了发非旋转Treap,感觉常数有点大
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=100010;
int n,m;
int a[N];
struct node{
node *l,*r;
int val,fix,size,minus;
node(){ }
node(int x):val(x),fix(rand()),size(1),l(NULL),r(NULL),minus(0){}
void Push(){
if(!minus) return ;
if(l) l->val-=minus,l->minus+=minus;
if(r) r->val-=minus,r->minus+=minus;
minus=0;
}
void Up(){
size=(l?l->size:0)+(r?r->size:0)+1;
}
int mark(int x){
val-=x; minus+=x;
}
}poor[N],*rt;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void rea(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
inline int Size(node *x){
return x?x->size:0;
}
typedef pair<node*,node*> Droot;
inline node *newnode(int x,int p){
poor[p].val=x; poor[p].fix=rand(); poor[p].size=1; return poor+p;
}
inline node *Merge(node *x,node *y){
if(!x||!y) return !x?y:x;
x->Push(); y->Push();
if(x->fix<y->fix){
x->r=Merge(x->r,y);
x->Up(); return x;
}
else{
y->l=Merge(x,y->l);
y->Up(); return y;
}
}
inline node *Query(int k){
node *x=rt;
while(x){
x->Push();
if(k==Size(x->l)+1) return x;
if(k>Size(x->l)) k-=Size(x->l)+1,x=x->r;
else x=x->l;
}
return 0;
}
inline int Rank(int k){
node *x=rt; int ret=0;
while(x){
x->Push();
if(x->val<k) ret+=Size(x->l)+1,x=x->r;
else x=x->l;
}
return ret+1;
}
Droot Split(node *x,int k){
if(!x) return Droot(NULL,NULL);
x->Push();
if(k<=Size(x->l)){
Droot ret=Split(x->l,k);
x->l=ret.second; x->Up();
ret.second=x; return ret;
}
else{
Droot ret=Split(x->r,k-Size(x->l)-1);
x->r=ret.first; x->Up();
ret.first=x; return ret;
}
}
bool Modify(int k){
int cur=Rank(k+1);
node *p=Query(cur);
if(!p||p->val>2*k) return false;
Droot x=Split(rt,cur-1);
Droot y=Split(x.second,1);
y.first->val-=k;
rt=Merge(x.first,y.second);
cur=Rank(y.first->val);
x=Split(rt,cur-1);
rt=Merge(x.first,Merge(y.first,x.second));
return true;
}
int opt,k;
int main(){
rea(n); rea(m);
for(int i=1;i<=n;i++) rea(a[i]);
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
poor[i]=node(a[i]),rt=Merge(rt,poor+i);
while(m--){
rea(opt); rea(k);
if(opt==1) printf("%d\n",Query(k)->val);
else{
while(Modify(k));
int cur;
if((cur=Rank(k+1))<=n){
Droot x=Split(rt,cur-1);
x.second->mark(k);
rt=Merge(x.first,x.second);
}
}
}
return 0;
}