出纳员是一个优秀的职业。
根据题意要构造一种数据结构使得能动态维护一个权值大于等于min的集合,并且支持查询排名等操作,数据范围来看复杂度是nlogn
由以上得出结论使用平衡树
我用的是treap,如果删的话就要把整颗左子树和根节点一起删再处理右子树的,其他操作和普通平衡树一样,可以看我之前那个模板。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,mi,ans; 4 char s[10]; 5 struct node 6 { 7 int l,r,size,w,v,rnd; 8 }t[200005]; 9 int rt,cnt; 10 void merge(int k) 11 { 12 t[k].size=t[t[k].l].size+t[t[k].r].size+t[k].w; 13 } 14 void lturn(int &k) 15 { 16 int rs=t[k].r; 17 t[k].r=t[rs].l; 18 t[rs].l=k; 19 t[rs].size=t[k].size; 20 merge(k); 21 k=rs; 22 } 23 void rturn(int &k) 24 { 25 int ls=t[k].l; 26 t[k].l=t[ls].r; 27 t[ls].r=k; 28 t[ls].size=t[k].size; 29 merge(k); 30 k=ls; 31 } 32 void add(int &k,int x) 33 { 34 if(!k) 35 { 36 k=++cnt; 37 t[k].v=x; 38 t[k].size=t[k].w=1; 39 t[k].rnd=rand(); 40 return; 41 } 42 t[k].size++; 43 if(t[k].v==x)t[k].w++; 44 else 45 { 46 if(t[k].v>x) 47 { 48 add(t[k].l,x); 49 if(t[t[k].l].rnd>t[k].rnd)rturn(k); 50 } 51 else 52 { 53 add(t[k].r,x); 54 if(t[t[k].r].rnd>t[k].rnd)lturn(k); 55 } 56 } 57 } 58 void del(int &k,int x) 59 { 60 if(!k)return; 61 if(t[k].v<x) 62 { 63 ans+=t[t[k].l].size+t[k].w; 64 del(t[k].r,x); 65 k=t[k].r; 66 } 67 else { 68 del(t[k].l,x); 69 if(t[t[k].l].rnd>t[k].rnd)rturn(k); 70 } 71 merge(k); 72 } 73 int delta; 74 int rank(int k,int x) 75 { 76 if(t[t[k].l].size+t[k].w>=x&&t[t[k].l].size<x)return t[k].v+delta; 77 else if(x<=t[t[k].l].size)return rank(t[k].l,x); 78 else return rank(t[k].r,x-t[t[k].l].size-t[k].w); 79 } 80 int main() 81 { 82 scanf("%d%d",&n,&mi); 83 int x; 84 for(int i=1;i<=n;++i) 85 { 86 scanf("%s%d",&s,&x); 87 if(s[0]=='I') 88 { 89 if(x>=mi) 90 { 91 add(rt,x-delta); 92 } 93 } 94 else if(s[0]=='A') 95 { 96 delta+=x; 97 } 98 else if(s[0]=='S') 99 { 100 delta-=x; 101 del(rt,mi-delta); 102 } 103 else 104 { 105 if(x>t[rt].size)puts("-1"); 106 else printf("%d ",rank(rt,t[rt].size-x+1)); 107 } 108 } 109 printf("%d ",ans); 110 return 0; 111 }