[luogu1486][NOI2004]鬱悶的出納員
阿新 • • 發佈:2018-12-22
看到這題覺得是平衡樹,因為有查詢第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; }