[luogu1486][NOI2004]郁闷的出纳员
看到这题觉得是平衡树,因为有查找第k大和插入删除操作。
但是我不会平衡树啊……所以拿树状数组写了一个伪平衡树。
对于插入操作,直接插,但是要减掉一个rec值。这个rec是什么意思等下说。
对于删除操作,直接删就行了。
对于A,我们肯定不行把所有数字都加一遍,于是利用rec,使rec这个变量加上修改值。所以员工真正的工资 = 他们的值 + rec
对于S,同理。但是这里我们需要不断查询最小值,和工资标准比较,然后开始删。
对于查询操作,直接查第k大即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 600005
#define lowbit(x) (x&(-x))
struct disc {
long long temp[MAXN],num[MAXN];
int tot,cnt;
disc() : tot(0),cnt(0) {}
void add(long long x) {
temp[++cnt] = x;
}
void unique() {
std::sort(temp+1,temp+1+cnt);
temp[0] = -2147483647;
for(int i=1;i<=cnt;++i)
if(temp[i]!=temp[i-1]) num[++tot] = temp[i];
}
int sub(long long x) {
int l = 1,r = tot;
while(l<r) {
int mid = (l+r+1)>>1;
if(num[mid]>x) r = mid - 1;
else l = mid;
}
return l;
}
}d;
struct record {
int num;
char opt;
}R[MAXN];
int C[MAXN];
int N,line,count = 0,ans = 0;
long long rec = 0;
inline char get_opt() {
char ch = getchar();
while(ch!='I'&&ch!='A'&&ch!='S'&&ch!='F') ch = getchar();
return ch;
}
inline int read() {
char ch = getchar(); int num = 0;
while(ch>'9'||ch<'0') ch = getchar();
while(ch>='0'&&ch<='9') num = num*10+ch-'0' , ch = getchar();
return num;
}
inline void update(int x,int u) {
for(;x<=d.tot;x+=lowbit(x)) C[x] += u;
}
inline int query(int x) {
int ans = 0;
for(;x>=1;x-=lowbit(x)) ans += C[x];
return ans;
}
inline int find_rk(int rk) {
int cur = 0,tot = 0;
for(int i=(1<<20);i>=1;i>>=1) {
cur += i;
if(cur>d.tot||tot+C[cur]>=rk) cur -= i;
else tot += C[cur];
}
return cur + 1;
}
inline void work() {
while(count>0) {
long long cur = d.num[ find_rk(1) ];
if(cur + rec < line) {
update( d.sub( cur ) , -1 );
count --;
ans ++;
}
else break;
}
}
int main() {
N = read(); line = read();
for(int i=1;i<=N;++i) {
R[i].opt = get_opt();
R[i].num = read();
if(R[i].opt=='I') d.add( R[i].num - rec );
else if(R[i].opt=='A') rec += (long long)R[i].num;
else if(R[i].opt=='S') rec -= (long long)R[i].num;
}
d.unique();
rec = 0;
for(int i=1;i<=N;++i) {
if(R[i].opt=='I'&&R[i].num>=line) {
count++;
update(d.sub( R[i].num - rec ),1);
}
else if(R[i].opt=='A') rec += (long long)R[i].num;
else if(R[i].opt=='S') {
rec -= (long long)R[i].num;
work();
}
else if(R[i].opt=='F'){
if(R[i].num>count) puts("-1");
else printf("%lld\n",d.num[find_rk(count - R[i].num + 1)] + rec);
}
}
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号