bzoj 1503 郁闷的出纳员
treap裸题...
还是要写一下,毕竟是第一个成功用treap维护的题,做个纪念吧
这题的中心思想其实很简单,就是插入+删除+查询排名为x的数
但是重点是,全体的标记怎么处理?
首先有一个很显然的思想,就是在修改全体的时候,我们不去修改全体的值,而是去修改界限
但这样做有一个很显然的问题:界限修改了,新来的值怎么办?
所以我们对这个思想进行一个优化,我们维护两个值,一个是minv,一个是lazy(仿线段树中懒惰标记),保证在任何时刻,minv+lazy=初始的minv
这样一来,每次新来一个值,我都把它和minv+lazy比较再考虑是否插入即可
而且在插入时,我们应该插入的时num-lazy,这样才能保证,对于treap中任何一个值,num+lazy=该时间下的真实值
剩下的就很简单了,由于数据范围中删除操作的次数很有限,所以我们可以暴力删除(当然也可以考虑整树删除,但这就过于麻烦了)
贴代码:
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <ctime> #define ls tree[rt].lson #define rs tree[rt].rson using namespace std; struct Treap { int lson; int rson; int huge; int rank; int val; int same; }tree[100005]; int n,minv,lazy; char s[2]; int tot=0; int rot=0; void update(int rt) { tree[rt].huge=tree[ls].huge+tree[rs].huge+tree[rt].same; } void lturn(int &rt) { int temp=rs; rs=tree[rs].lson; tree[temp].lson=rt; tree[temp].huge=tree[rt].huge; update(rt); rt=temp; } void rturn(int &rt) { int temp=ls; ls=tree[ls].rson; tree[temp].rson=rt; tree[temp].huge=tree[rt].huge; update(rt); rt=temp; } void ins(int &rt,int v) { if(!rt) { rt=++tot; tree[rt].huge=1; tree[rt].same=1; tree[rt].val=v; tree[rt].rank=rand(); return; } tree[rt].huge++; if(v==tree[rt].val) { tree[rt].same++; return; }else if(v<tree[rt].val) { ins(ls,v); if(tree[ls].rank<tree[rt].rank) { rturn(rt); } }else { ins(rs,v); if(tree[rs].rank<tree[rt].rank) { lturn(rt); } } } void del(int &rt,int v) { if(!rt) { return; } if(tree[rt].val==v) { if(tree[rt].same>1) { tree[rt].huge--; tree[rt].same--; return; }else { if(ls*rs==0) { rt=ls+rs; return; }else if(tree[ls].rank<tree[rs].rank) { rturn(rt); del(rt,v); }else { lturn(rt); del(rt,v); } return; } } tree[rt].huge--; if(tree[rt].val>v) { del(ls,v); }else { del(rs,v); } } int ans=0; bool flag=0; void query_pro(int rt,int v)//求前驱 { if(rt==0) { return; } if(tree[rt].val<v) { ans=tree[rt].val; flag=1; query_pro(rs,v); }else { query_pro(ls,v); } } int query_num(int rt,int v)//查询排名为x的数 { if(rt==0) { return 0; } if(tree[rs].huge<v&&tree[rt].same+tree[rs].huge>=v) { return tree[rt].val; }else if(tree[rs].huge>=v) { return query_num(rs,v); }else { return query_num(ls,v-tree[rs].huge-tree[rt].same); } } inline int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int main() { n=read(),minv=read(); int cnt=0; int cot=0; for(int i=1;i<=n;i++) { scanf("%s",s); if(s[0]=='I') { int x=read(); if(x-lazy<minv) { continue; }else { cot++; ins(rot,x-lazy); } }else if(s[0]=='A') { int x=read(); lazy+=x; minv-=x; }else if(s[0]=='S') { int x=read(); lazy-=x; minv+=x; ans=0; flag=0; query_pro(rot,minv); while(flag) { del(rot,ans); ans=0; flag=0; cot--; cnt++; query_pro(rot,minv); } }else { int x=read(); if(x>cot) { printf("-1\n"); continue; }else { printf("%d\n",query_num(rot,x)+lazy); } } } printf("%d\n",cnt); return 0; }