BZOJ1503 郁闷的出纳员

出纳员是一个优秀的职业。

根据题意要构造一种数据结构使得能动态维护一个权值大于等于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\n",rank(rt,t[rt].size-x+1));
107         }
108     }
109     printf("%d\n",ans);
110     return 0;
111 }

 

生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。
posted @ 2017-12-01 21:00  大奕哥&VANE  阅读(136)  评论(0编辑  收藏  举报