BZOJ1503:[NOI2004]郁悶的出納員
阿新 • • 發佈:2018-11-21
htm getchar sin mat nlog += getch 的人 com 加上\(now-mn\)。
淺談\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html
淺談\(fhq\)_\(treap\):https://www.cnblogs.com/AKMer/p/9981274.html
題目傳送門:https://www.lydsy.com/JudgeOnline/problem.php?id=1503
對於每個人都加工資,我們可以直接降低最低工資標準來判斷,對於減工資,我們就加標準,那麽每個人與最低標準的差值始終是正確的。
我們記一個\(now\)表示當前最低工資標準,記一個\(mn\)表示初始工資標準。那麽每次進來一個工資為\(k\)的人,我們要使他與最低工資標準的差值是正確的,就應該使\(k\)
而每個人與當前最低標準的差值加上初始標準,就是真實工資。
時間復雜度:\(O(nlogn)\)
空間復雜度:\(O(n)\)
\(splay\)版代碼如下:
#include <cstdio> #include <iostream> using namespace std; const int maxn=1e5+5; char s[25]; int n,mn,now,tot; int read() { int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } struct Splay { int tot,root; int fa[maxn],son[maxn][2]; int siz[maxn],cnt[maxn],val[maxn]; int newnode(int v) { val[++tot]=v; siz[tot]=cnt[tot]=1; return tot; } int find(int v) { int u=root; while(val[u]!=v) { if(val[u]>v) {if(son[u][0])u=son[u][0];else break;} if(val[u]<v) {if(son[u][1])u=son[u][1];else break;} } return u; } int t(int u) { return son[fa[u]][1]==u; } void update(int p) { siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]]; } void rotate(int u) { int ret=t(u),f=fa[u],s=son[u][ret^1]; son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f; fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u; fa[f]=u;update(f);update(u); } void splay(int u) { while(fa[u]) { if(fa[fa[u]]) { if(t(fa[u])==t(u))rotate(fa[u]); else rotate(u); } rotate(u); } root=u; } void ins(int v) { if(!root) {root=newnode(v);return;} int u=find(v); if(val[u]==v) {siz[u]++;cnt[u]++;splay(u);return;} fa[newnode(v)]=u;son[u][v>val[u]]=tot; splay(tot); } void check() { int u=find(now);splay(u); if(val[u]<now) { u=son[u][1]; while(son[u][0])u=son[u][0]; splay(u); } fa[son[u][0]]=0; son[u][0]=0;update(u); } int get_val(int k) { int u=root,rk=siz[u]-k+1; if(rk<1)return -1; while(rk) { if(siz[son[u][0]]>=rk)u=son[u][0]; if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break; if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1]; } return val[u]+mn-now; } }T; int main() { n=read(),now=mn=read(); for(int i=1;i<=n;i++) { scanf("%s",s+1); int k=read(); if(s[1]=='I') { k+=now-mn; if(k<now)continue; T.ins(k);tot++; } if(s[1]=='A')now-=k; if(s[1]=='S') { now+=k; T.check(); } if(s[1]=='F')printf("%d\n",T.get_val(k)); } printf("%d\n",tot-T.siz[T.root]); return 0; }
\(fhq\)_\(treap\)版代碼如下:
#include <ctime> #include <cstdio> #include <algorithm> using namespace std; typedef pair<int,int> pii; const int maxn=1e5+5; char s[25]; int n,m,tot,mn,now; int read() { int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } struct fhq_treap { int tot,root; int fix[maxn],son[maxn][2]; int siz[maxn],cnt[maxn],val[maxn]; int newnode(int v) { val[++tot]=v;fix[tot]=rand(); siz[tot]=cnt[tot]=1;return tot; } int getkth(int u,int v,bool &bo,int delta) { if(!u)return 0;int ans=0; if(val[u]>v)ans=getkth(son[u][0],v,bo,delta); else if(val[u]==v) { if(delta)cnt[u]+=delta,siz[u]+=delta,bo=1; return siz[son[u][0]]; } else ans=siz[son[u][0]]+cnt[u]+getkth(son[u][1],v,bo,delta); if(bo)siz[u]+=delta;return ans; } void update(int p) { siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]]; } pii split(int u,int rk) { if(!rk)return make_pair(0,u); if(rk==siz[u])return make_pair(u,0); if(siz[son[u][0]]>=rk) { pii tmp=split(son[u][0],rk); son[u][0]=tmp.second,update(u); return make_pair(tmp.first,u); } else { pii tmp=split(son[u][1],rk-siz[son[u][0]]-cnt[u]); son[u][1]=tmp.first,update(u); return make_pair(u,tmp.second); } } int merge(int a,int b) { if(!a||!b) return a+b; if(fix[a]>fix[b])return son[a][1]=merge(son[a][1],b),update(a),a; else return son[b][0]=merge(a,son[b][0]),update(b),b; } void ins(int v) { bool bo=0;int rk=getkth(root,v,bo,1); if(bo)return;pii tmp=split(root,rk); root=merge(merge(tmp.first,newnode(v)),tmp.second); } void check() { bool bo=0; int rk=getkth(root,now,bo,0); pii tmp=split(root,rk);root=tmp.second; } int get_val(int k) { int u=root,rk=siz[u]-k+1; if(rk<1)return -1; while(rk) { if(siz[son[u][0]]>=rk)u=son[u][0]; if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break; if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1]; } return val[u]+mn-now; } }T; int main() { srand(time(0)); n=read(),now=mn=read(); for(int i=1;i<=n;i++) { scanf("%s",s+1);int k=read(); if(s[1]=='I') { k+=now-mn; if(k<now)continue; T.ins(k);tot++; } if(s[1]=='A')now-=k; if(s[1]=='S') { now+=k; T.check(); } if(s[1]=='F')printf("%d\n",T.get_val(k)); } printf("%d\n",tot-T.siz[T.root]); return 0; }
BZOJ1503:[NOI2004]郁悶的出納員