【平衡树】BZOJ1503(NOI2004)[郁闷的出纳员]题解
2017-06-30 08:28
501 查看
题目概述
ps:员工一旦发现自己的工资低于工资下界,就会离开公司,再也不会回来了。
解题报告
这道题有插入有删除且求第k大显然用平衡树做,只不过加工资和减工资不是很常规的操作。想一想可以发现加工资和减工资用Lazy-tag就可以解决,但是实际上并不需要,因为加工资和减工资表面看上去是员工工资的变化,实际上我们也可以看做是工资下界发生了变化!所以我们不用去调整每个员工的工资,只需要调整工资下界即可,但这样一来新员工的工资就不是读入的工资了,要加上当前工资下界MIN减去最初工资下界fst,同理,查询的答案也需要减去MIN-fst。比较坑爹的是,新员工如果工资直接比工资下界低离开公司,是不算入离开人数的……
由于最近学了下SBT,于是SBT和Treap都抄板子打了一遍……
示例程序
Treap。#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; const int MAXINT=((1<<30)-1)*2+1,maxn=100000; int te,fst,MIN,ans; struct Treap { Treap* son[2];int x,w,si,p; Treap(int K,Treap* P,int S=1) {si=w=S;x=K;son[0]=son[1]=P;p=rand();} int cmp(int k) {if (k<x) return 0;if (k==x) return -1;if (k>x) return 1;} void Pushup() {si=son[0]->si+son[1]->si+w;} }; Treap nil(0,&nil,0),*null=&nil,*ro=null; void Rotate(Treap* &id,int d) { Treap* t=id->son[d^1];id->son[d^1]=t->son[d];t->son[d]=id; id->Pushup();t->Pushup();id=t; } void Insert(Treap* &id,int x) { if (id==null) {id=new Treap(x,null);return;} int d=id->cmp(x); if (d==-1) id->w++; else { Insert(id->son[d],x); if (id->son[d]->p>id->p) Rotate(id,d^1); } id->Pushup(); } void Delete(Treap* &id,int x) { if (id==null) return; int d=id->cmp(x); if (d==-1) { if (id->w>1) id->w--; else if (id->son[0]==null) id=id->son[1]; else if (id->son[1]==null) id=id->son[0]; else { int son;if (id->son[0]->p>id->son[1]->p) son=0; else son=1; Rotate(id,son^1);if (id==null) return; Delete(id->son[son^1],x); } if (id==null) return; } else Delete(id->son[d],x); id->Pushup(); } int getkth(Treap* id,int k) { if (id==null) return -1; if (id->son[0]->si<k&&k<=id->son[0]->si+id->w) return id->x-MIN+fst; else if (k<=id->son[0]->si) return getkth(id->son[0],k); else return getkth(id->son[1],k-(id->son[0]->si+id->w)); } int getpre(Treap* id,int k) { if (id==null) return -MAXINT; int d=id->cmp(k); if (d==1) { int now=id->x,tem=getpre(id->son[1],k); if (tem!=-MAXINT) return tem; else return now; } else return getpre(id->son[0],k); } char readc() { static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,100000,stdin); if (l==r) return EOF; else return *l++; } bool Eoln(char ch) {return ch==10||ch==13||ch==EOF;} int readi(int &x) { int tot=0,f=1;char ch=readc(),lst=ch; while ('9'<ch||ch<'0') {if (ch==EOF) return EOF;lst=ch;ch=readc();} if (lst=='-') f=-f; while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=readc(); x=tot*f; return Eoln(ch); } char getrch() {char ch=readc();while ('Z'<ch||ch<'A') ch=readc();return ch;} int main() { freopen("program.in","r",stdin); freopen("program.out","w",stdout); readi(te);readi(fst);MIN=fst; while (te--) { int x; switch(getrch()) { case 'I':readi(x);if (x+MIN-fst>=MIN) Insert(ro,x+MIN-fst);break; case 'A':readi(x);MIN-=x;break; case 'S':readi(x);MIN+=x;break; case 'F':readi(x);x=ro->si-x+1;printf("%d\n",getkth(ro,x));break; } for (int now=getpre(ro,MIN);now!=-MAXINT;now=getpre(ro,MIN)) Delete(ro,now),ans++; } printf("%d\n",ans); return 0; }
SBT。
#include<cstdio> #include<algorithm> using namespace std; const int MAXINT=((1<<30)-1)*2+1; int te,fst,MIN,ans; struct node { node* son[2];int si,key; node(int k,node* p,int s=1) {si=s;key=k;son[0]=son[1]=p;} int cmp(int k) {return k>=key;} void Pushup() {si=son[0]->si+1+son[1]->si;} }; node nil(0,&nil,0); typedef node* P_node; P_node null=&nil,ro=null; void Rotate(P_node &p,int d) { P_node t=p->son[d^1];p->son[d^1]=t->son[d];t->son[d]=p; p->Pushup();t->Pushup();p=t; } void Maintain(P_node &p,bool fl) { P_node L=p->son[0],R=p->son[1]; if (!fl) if (L->son[0]->si>R->si) Rotate(p,1); else if (L->son[1]->si>R->si) Rotate(p->son[0],0),Rotate(p,1); else return; else if (R->son[1]->si>L->si) Rotate(p,0); else if (R->son[0]->si>L->si) Rotate(p->son[1],1),Rotate(p,0); else return; Maintain(p->son[0],0);Maintain(p->son[0],1); Maintain(p->son[1],0);Maintain(p->son[1],1); Maintain(p,0);Maintain(p,1); } void Insert(P_node &p,int k) { if (p==null) {p=new node(k,null);return;} int d=p->cmp(k);Insert(p->son[d],k); p->Pushup();Maintain(p,d); } int Delete(P_node &p,int k) { int d=p->cmp(k),now; if (k==p->key||p->son[d]==null) { now=p->key; if (p->son[0]==null) p=p->son[1]; else if (p->son[1]==null) p=p->son[0]; else p->key=Delete(p->son[0],p->key),p->Pushup(),Maintain(p,1); return now; } now=Delete(p->son[d],k); p->Pushup();Maintain(p,d^1); return now; } int getkth(P_node p,int k) { if (p==null) return -1; if (k==p->son[0]->si+1) return p->key+fst-MIN; else if (k<=p->son[0]->si) return getkth(p->son[0],k); else return getkth(p->son[1],k-p->son[0]->si-1); } int getpre(P_node p,int k) { if (p==null) return -MAXINT; if (k>p->key) return max(p->key,getpre(p->son[1],k)); else return getpre(p->son[0],k); } char readc() { static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,100000,stdin); if (l==r) return EOF; else return *l++; } bool Eoln(char ch) {return ch==10||ch==13||ch==EOF;} int readi(int &x) { int tot=0,f=1;char ch=readc(),lst=ch; while ('9'<ch||ch<'0') {if (ch==EOF) return EOF;lst=ch;ch=readc();} if (lst=='-') f=-f; while ('0'<=ch&&ch<='9') tot=tot*10+ch-48,ch=readc(); x=tot*f; return Eoln(ch); } char getrch() {char ch=readc();while ('Z'<ch||ch<'A') ch=readc();return ch;} int main() { freopen("program.in","r",stdin); freopen("program.out","w",stdout); readi(te);readi(fst);MIN=fst; while (te--) { int x; switch(getrch()) { case 'I':readi(x);if (x+MIN-fst>=MIN) Insert(ro,x+MIN-fst);break; case 'A':readi(x);MIN-=x;break; case 'S':readi(x);MIN+=x;break; case 'F':readi(x);x=ro->si-x+1;printf("%d\n",getkth(ro,x));break; } for (int now=getpre(ro,MIN);now!=-MAXINT;now=getpre(ro,MIN)) Delete(ro,now),ans++; } printf("%d\n",ans); return 0; }
相关文章推荐
- [BZOJ1503][NOI2004]郁闷的出纳员(平衡树splay)
- BZOJ 1503 郁闷的出纳员(平衡树)(NOI 2004)
- bzoj 1503 [NOI2004]郁闷的出纳员 平衡树(treap/Splay)
- [BZOJ1503][NOI2004]郁闷的出纳员(平衡树splay)
- bzoj 1503: [NOI2004]郁闷的出纳员 平衡树treap
- [bzoj 1503][NOI 2004]郁闷的出纳员(平衡树)
- 【BZOJ】1503 [NOI2004]郁闷的出纳员 平衡树
- [BZOJ]1503: [NOI2004]郁闷的出纳员
- 【NOI2004】【BZOJ1503】【重制版本(可过BZOJ+加速)】郁闷的出纳员
- bzoj 1503: [NOI2004]郁闷的出纳员
- [bzoj1503][NOI2004]郁闷的出纳员——splay
- 【BZOJ】1503: [NOI2004]郁闷的出纳员(Splay)
- 【bzoj 1503】 [NOI2004]郁闷的出纳员
- bzoj 1503 [NOI2004]郁闷的出纳员 splay
- bzoj 1503: [NOI2004]郁闷的出纳员
- BZOJ 1503 [NOI2004]郁闷的出纳员 (Splaytree)
- BZOJ1503 NOI2004 郁闷的出纳员 题解&代码
- BZOJ1503 [NOI2004]郁闷的出纳员
- bzoj 1503: [NOI2004]郁闷的出纳员 splay
- BZOJ_1503_[NOI2004]郁闷的出纳员_权值线段树