1. 程式人生 > >BZOJ[NOI2004]郁悶的出納員 | Splay板子題

BZOJ[NOI2004]郁悶的出納員 | Splay板子題

oot names ace i++ def shu bzoj pro pre

題目:

洛谷也能評測....還有我wa了10多次的記錄233


題解:

不要想得太復雜,搞一個全局變量記錄一下工資的改變量Delta,這樣可以等詢問的時候就輸出val+Delta,然後插入的時候插入x-Delta

不要想會不會有員工工資一樣,直接插入就好,這樣省不少代碼量.

對於降工資操作,插入一個min-Delta節點,ans+=左子樹大小,右兒子作為新的根節點

直接走的員工不要算ans

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 200010
#define which(x) (ls[fa[(x)]]==x)
using
namespace std; int sz[N],ls[N],rs[N],val[N],fa[N],n,lim,k,tot,delta,ans,root; char s[N]; void Pushup(int x){sz[x]=1+sz[ls[x]]+sz[rs[x]];} void Rotate(int u) { int v=fa[u],w=fa[v],b=which(u)?rs[u]:ls[u]; if (w) which(v)?ls[w]=u:rs[w]=u; which(u)?(ls[v]=b,rs[u]=v):(rs[v]=b,ls[u]=v); fa[u]
=w,fa[v]=u; if (b) fa[b]=v; Pushup(v);Pushup(u); } void Splay(int u) { while (fa[u]) { if (fa[fa[u]]) if (which(u)==which(fa[u])) Rotate(fa[u]); else Rotate(u); Rotate(u); } root=u; } void Insert(int x) { int cur=root,v=0,dir; while
(cur) { if (val[v=cur]>=x) cur=ls[cur],dir=0; else cur=rs[cur],dir=1; sz[v]++; } val[++tot]=x,fa[tot]=v,sz[tot]=1; if (v) dir==0?ls[v]=tot:rs[v]=tot; Splay(tot); } int getkth(int k) { int cur=root; while (cur) { if (sz[ls[cur]]>=k) cur=ls[cur]; else if (sz[ls[cur]]+1>=k) return val[cur]; else k-=sz[ls[cur]]+1,cur=rs[cur]; } return val[cur]; } void Delete() { Insert(lim-delta); ans+=sz[ls[root]]; root=rs[root],fa[root]=0; } int main() { scanf("%d%d",&n,&lim); for (int i=1;i<=n;i++) { scanf("%s%d",s+1,&k); if (s[1]==I) if (k>=lim) Insert(k-delta); if (s[1]==A) delta+=k; if (s[1]==S) delta-=k,Delete(); if (s[1]==F) if (sz[root]<k || root==0) puts("-1"); else printf("%d\n",getkth(sz[root]-k+1)+delta); } printf("%d",ans); return 0; }

BZOJ[NOI2004]郁悶的出納員 | Splay板子題