权值线段树+动态开点[NOI2004]郁闷的出纳员
#include<iostream> #include<stdio.h> #include<algorithm> #include<string.h> #define rep(i,j,k) for(int i=j;i<=k;i++) #define per(i,j,k) for(int i=j;i>=k;i--) using namespace std; const int maxx = 2e5+50; int lson[maxx*18],rson[maxx*18],sum[maxx*18]; int tot=1,root=1; bool laze[maxx*18]; void push_down(int x){ if(laze[x]){ if(!lson[x])lson[x]=++tot; if(!rson[x])rson[x]=++tot; sum[lson[x]]=0; sum[rson[x]]=0; laze[lson[x]]=1; laze[rson[x]]=1; laze[x]=0; } } void inserts(int l,int r,int x,int &p){ if(!p)p=++tot; if (l==r){ sum[p]++; return; } int mid=(l+r)>>1; push_down(p); if (x<=mid){ inserts(l,mid,x,lson[p]); }else { inserts(mid+1,r,x,rson[p]); } sum[p]=sum[lson[p]]+sum[rson[p]]; } void update(int l,int r,int ul,int ur,int &p){ if (!p)p=++tot; if (ul<=l && r<=ur){ sum[p]=0; laze[p]=1; return; } push_down(p); int mid=(l+r)>>1; if(ul<=mid)update(l,mid,ul,ur,lson[p]); if(ur>mid)update(mid+1,r,ul,ur,rson[p]); sum[p]=sum[lson[p]]+sum[rson[p]]; } int kth(int l,int r,int k,int &p){ if(l==r){ return l; } int mid=(l+r)>>1; push_down(p); if(k<=sum[lson[p]]){ return kth(l,mid,k,lson[p]); }else { return kth(mid+1,r,k-sum[lson[p]],rson[p]); } } int main(){ int n,m,w; int add=0,nowmin,num=0; char op[10]; while(~scanf("%d%d",&n,&nowmin)){ rep(i,1,n){ scanf("%s%d",op,&w); if (op[0]=='I'){ //减去影响后如果起薪小于工资下界 if (w-add<nowmin)continue; //他的工资实际上应该是他的起 inserts(-maxx,maxx,w-add,root); num++; }else if(op[0]=='A'){ //偏移应该加上 add+=w; //同时此时要求最低的工资降低 nowmin-=w; }else if(op[0]=='S'){ add-=w; nowmin+=w; //比最低工资低的值全部赋值为0 update(-maxx,maxx,-maxx,nowmin-1,root); }else { //如果所有人被开除 if(w>sum[1]){ printf("-1\n"); continue; }else { //查询剩下的第K大,并且要加上偏移 //其实等价于查询当前第K大=总数-第K小+1 printf("%d\n",kth(-maxx,maxx,sum[1]-w+1,root)+add); } } } printf("%d\n",num-sum[1]); } return 0; }
有不懂欢迎咨询
QQ:1326487164(添加时记得备注)