题意:插入一个数,全体加,全体减,删除小于一个数的所有数,求$k$大
全局标记然后平衡树直接搞就行了
删除操作不断的找最小值然后删除复杂度是对的,然而$Candy?$这个沙茶找最小没有判$x==0$超时郁闷了好长时间....
或者你也可以乱搞一个$treap$的左子树删除...时间差了$50ms$左右
然后对于第一种做法潸然生日再次自带$50ms$常数
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define lc t[x].l #define rc t[x].r const int N=1e5+5; int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int n,lim,all,v; char s[5]; struct Node{ int l,r,v,w,size,rnd; }t[N]; int sz,root; inline void update(int x){t[x].size=t[lc].size+t[rc].size+t[x].w;} inline void rturn(int &x){ int c=lc;lc=t[c].r;t[c].r=x; t[c].size=t[x].size;update(x);x=c; } inline void lturn(int &x){ int c=rc;rc=t[c].l;t[c].l=x; t[c].size=t[x].size;update(x);x=c; } void treIns(int &x,int v){ if(x==0){ x=++sz; t[x].l=t[x].r=0;t[x].v=v; t[x].w=t[x].size=1; t[x].rnd=rand(); }else{ t[x].size++; if(v==t[x].v) t[x].w++; else if(v<t[x].v){ treIns(lc,v); if(t[lc].rnd<t[x].rnd) rturn(x); }else{ treIns(rc,v); if(t[rc].rnd<t[x].rnd) lturn(x); } } } void treDel(int &x,int v){ if(x==0) return; if(v==t[x].v){ if(t[x].w>1) t[x].w--,t[x].size--; else if(!lc||!rc) x=lc|rc; else if(t[lc].rnd<t[rc].rnd) rturn(x),treDel(x,v); else lturn(x),treDel(x,v); }else{ t[x].size--; if(v<t[x].v) treDel(lc,v); else treDel(rc,v); } } int kth(int x,int k){ if(x==0) return 0; if(k<=t[lc].size) return kth(lc,k); else if(k<=t[lc].size+t[x].w) return t[x].v; else return kth(rc,k-t[lc].size-t[x].w); } inline int findMin(int x){ if(x==0) return 1e9; while(lc) x=lc; return t[x].v; } int Erase(int &x,int v){ if(x==0) return 0; int _; if(t[x].v<v) {_=t[lc].size+t[x].w,x=rc;return _+Erase(x,v);} else {_=Erase(lc,v);t[x].size-=_;return _;} } int main(int argc, const char * argv[]) { freopen("in","r",stdin); srand(317); n=read();lim=read(); int delcnt=0; for(int i=1;i<=n;i++){ scanf("%s",s);v=read(); if(s[0]=='I') {if(v>=lim) treIns(root,v-all);} else if(s[0]=='A') all+=v; else if(s[0]=='S'){ all-=v; //int mn=findMin(root);//printf("mn %d ",mn); //while(mn+all<lim) treDel(root,mn),delcnt++,mn=findMin(root); delcnt+=Erase(root,lim-all); }else{ if(v>t[root].size) puts("-1"); else printf("%d ",kth(root,t[root].size-v+1)+all); } } printf("%d",delcnt); }