[bzoj1503][NOI2004]郁闷的出纳员
题目很劲爆--OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?
大概就是要支持查询k大,区间改和删点。 $n\leqslant 10^{5}$
题解:就是一道很裸的平衡树呗。然后我突然决定用这道题学学treap,然后就莫名调了好久..
#include<iostream> #include<cstdio> #define MN 100000 #define INF 0x7FFFFFFF using namespace std; inline int read() { int x = 0 , f = 1; 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; } inline int Ran() { static int x=23333; x^=(x<<13);x^=(x>>17);x^=(x<<5);return x; } char op[5]; int fa[MN+5],c[MN+5][2],size[MN+5],val[MN+5],nn[MN+5],n,K,s[MN+5],cnt=0,rt=0,ans=0; inline void update(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;} void pushdown(int x) { int l=c[x][0],r=c[x][1]; val[l]+=val[x];val[r]+=val[x]; nn[l]+=val[x];nn[r]+=val[x]; val[x]=0; } void rotate(int x) { int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; c[z][c[z][1]==y]=x; if(y==rt)rt=x; fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; update(y);update(x); } void ins(int x,int rk) { // if(++tms>MN*100)exit(0); if(!x)rt=++cnt; else { int t=(rk>nn[x]);pushdown(x);++size[x]; while(c[x][t]) {x=c[x][t];++size[x];pushdown(x);t=rk>nn[x];} c[x][t]=++cnt;fa[cnt]=x; } size[cnt]=1;s[cnt]=Ran();nn[cnt]=rk; while(fa[cnt]&&s[cnt]>s[fa[cnt]])rotate(cnt); } int find(int x,int rk) { if(!x)return -1; if(val[x]) pushdown(x); int l=size[c[x][0]]; if(l+1==rk)return x; if(l+1<rk) return find(c[x][1],rk-l-1); return find(c[x][0],rk); } void del(int x) { c[fa[x]][0]=c[x][1];fa[c[x][1]]=fa[x];if(x==rt) rt=c[x][1]; while(x=fa[x])update(x); } int main() { n=read();K=read();s[0]=-INF; for(int i=1;i<=n;i++) { scanf("%s",op);int x=read(); if(op[0]=='I') {if(x>=K)ins(rt,x);} if(op[0]=='S') {nn[rt]-=x;val[rt]-=x;while((x=find(rt,1))>0&&nn[x]<K) del(x),++ans;} if(op[0]=='F') {printf("%d\n",(x=find(rt,size[rt]-x+1))==-1?-1:nn[x]);} if(op[0]=='A') {nn[rt]+=x;val[rt]+=x;} } printf("%d\n",ans); return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream