BZOJ 1503 郁闷的出纳员
解析:题目不难, 算是Splay区间操作入门题, 主要就是考虑每次减薪操作时, 直接将当前的薪水小于min限制的人员全部删掉即可, 加薪的时候直接在root处打上tag 然后在合适的时候进行pushdown即可, 注意select单个node的时候, 一定样pushdown(),不然会WA飞.
Source:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline void R(int &v)
{
char c=0;
bool p=true;
v=0;
while(!isdigit(c))
{
if(c=='-')
p=false;
c=getchar();
}
while(isdigit(c))
{
v=(v<<3)+(v<<1)+(c^'0');
c=getchar();
}
if(!p)
v=-v;
}
const int MAXN=1e6;
const int INF=~0u>>1;
template
struct memorypool
{
T buf[size], *tail, *st[size];
int top;
inline T *alloc() { return top ? st[--top] : tail++; }
inline void recycle(T *x) { st[top++] = x; }
memorypool() : top(0), tail(buf) {}
};
template
struct Splay {
enum Relation { L = 0, R = 1 };
struct node {
node *child[2], *parent, **root;
T value, lazy;
int size, count;
inline void init(node *parent, node **root, const T &value)
{
this->parent = parent, this->value = value, this->root = root;
this->count = this->size = 1, this->lazy = 0, child[L] = child[R] = NULL;
}
// inline Relation relation() { return this == parent->child[L] ? L : R; }
inline void recycle(memorypool &pool)
{
if (child[L]) pool.recycle(child[L]);
if (child[R]) pool.recycle(child[R]);
}
inline void updata(const T &delta)
{
if (this->value != INF && this->value != -INF) this->value += delta;
this->lazy += delta;
}
inline void pushdown()
{
if (lazy) {
if (child[L]) child[L]->updata(lazy);
if (child[R]) child[R]->updata(lazy);
lazy = 0;
}
}
inline Relation relation() { return this == parent->child[L] ? L : R; }
inline void maintain() { pushdown(), size = count + (child[L] ? child[L]->size : 0) + (child[R] ? child[R]->size : 0); }
inline void rotate()
{
pushdown();
Relation x = relation();
node *oldParent = parent;
if (oldParent->parent) oldParent->parent->child[oldParent->relation()] = this;
parent = oldParent->parent, oldParent->child[x] = child[x ^ 1];
if (child[x ^ 1]) child[x ^ 1]->parent = oldParent;
child[x ^ 1] = oldParent, oldParent->parent = this, oldParent->maintain(), maintain();
if (!parent) *root = this;
}
inline void splay(node *targetParent = NULL)
{
while (parent != targetParent) {
parent->pushdown(), pushdown();
if (parent->parent == targetParent) rotate();
else {
parent->parent->pushdown();
if (parent->relation() == relation()) parent->rotate(), rotate();
else rotate(), rotate();
}
}
}
inline node *precursor()
{
splay();
node *v = child[L];
while (v->child[R]) v = v->child[R];
return v;
}
inline node *successor()
{
splay();
node *v = child[R];
while (v->child[L]) v = v->child[L];
return v;
}
inline int rank() { return child[L] ? child[L]->size : 0; }
} *root;
memorypool pool;
Splay() : root(NULL) { insert(INF), insert(-INF); }
inline node *find(const T &value)
{
node *v = root;
while (v && value != v->value) v->pushdown(), v = (value < v->value ? v->child[L] : v->child[R]);
return v ? (v->splay(), v) : NULL;
}
inline node *insert(const T &value)
{
node *v = find(value);
if (v) return v->count++, v->maintain(), v;
node **target = &root, *parent = NULL;
while (*target) parent = *target, parent->pushdown(), parent->size++, target = (value < parent->value ? &parent->child[L] : &parent->child[R]);
return *target = pool.alloc(), (*target)->init(parent, &root, value), (*target)->splay(), root;
}
inline int rank(const T &value)
{
node *v=find(value);
if(v) return v->rank();
else
{
node *v=insert(value);
register int ans=v->rank();
return erase(v), ans;
}
}
inline const T &precursor(const T &value)
{
node *v=find(value);
if(v) return v->precursor()->value;
else
{
node *v=insert(value);
const T &ans=v->precursor()->value;
return erase(v), ans;
}
}
inline const T &successor(const T &value)
{
node *v=find(value);
if(v) return v->successor()->value;
else
{
node *v=insert(value);
const T &ans=v->successor()->value;
return erase(v), ans;
}
}
inline void updata(const T &value) { root->updata(value); }
inline const T &select(int k) {
k++;
node *v = root;
while (v->pushdown(), !(v->rank() < k && v->rank() + v->count >= k)) v = (k <= v->rank() ? v->child[L] : (k -= v->rank() + v->count, v->child[R]));
return v->splay(), v->value;
}
inline void erase(node *l, node *r) {
node *pre = l->precursor(), *suc = r->successor();
pre->splay(), suc->splay(pre), suc->child[L]->recycle(pool);
pool.recycle(suc->child[L]), suc->child[L] = NULL, suc->maintain(), pre->maintain();
}
inline void erase(node *v) { v->count > 1 ? v->count-- : erase(v, v); }
inline void erase(const T &l, const T &r) {
node *vl = find(l), *vr = find(r);
if (!vl) vl = insert(l);
if (!vr) vr = insert(r);
erase(vl, vr);
}
inline int size() { return root->size - 2; }
};
Splay splay;
int main()
{
int n,min,x,ans,cnt=0;
char c[10];
R(n),R(min);
while(n--)
{
scanf("%s",c),R(x);
if(c[0]=='I')
{
if(x>=min)
{
splay.insert(x);
cnt++;
}
}
else if(c[0]=='A') splay.updata(x);
else if(c[0]=='S') splay.updata(-x),splay.erase(-INF+1,min-1);
else if(c[0]=='F')
{
splay.erase(-INF+1,min-1);
if(x>splay.size())
cout<<"-1"<<'\n';
else
cout<


本文介绍了一道关于Splay树区间操作的经典题目——“郁闷的出纳员”,通过此题详细讲解了如何利用Splay树实现高效的数据更新与查询操作。文章重点介绍了在面对加薪、减薪等区间操作时,如何运用懒标记(Lazy Tag)进行优化,并讨论了在选择节点时需要注意的细节。

732

被折叠的 条评论
为什么被折叠?



