郁闷的出纳员 (splay的区间标记模板,删除区间,add标记,类似线段树)

来源:互联网 发布:东华金云网络股份公司 编辑:程序博客网 时间:2024/05/29 14:49

往事不堪回首。。

这个题目花了2天时间才A了。

思路照搬SnowyJone大牛:http://www.cnblogs.com/w007878/p/3453023.html Orz。。

此处可找到数据:http://tieba.baidu.com/p/1217076472

真是虐心的两天,整个人都瘦了。。

当然也算值了,为的就是splay的模板大计!

操作中较为难办的就是相同数和删除区间。

相同数解决方法:保证每个数都不同,用num记录其个数

删除区间[l, r]:实际上是将l的前驱p,r的后继q,将p移动到q的子节点,直接删除p的右子树,然后更新即可。相比对序列操作的l 和 r可能不存在,需要特殊处理一下。

再者就是各种细节:

  1. 初始工资小于MIN的不算踢出的。。

  2. 各种PUSHUP,PUSHDOWN注意。

转载 : http://www.cnblogs.com/Mathics/p/3978047.html

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cstdlib>#include <cmath>#include <utility>#include <vector>#include <queue>#include <map>#include <set>#define max(x,y) ((x)>(y)?(x):(y))#define min(x,y) ((x)>(y)?(y):(x))#define INF 0x3f3f3f3f#define MAXN 100005using namespace std;int cnt, rt;int Add[MAXN],ans;struct Tree{    int key, num, size, fa, son[2];}T[MAXN];inline void PushUp(int x){    T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+T[x].num;}inline void PushDown(int x){    if(Add[x])    {        if(T[x].son[0])        {            T[T[x].son[0]].key+=Add[x];            Add[T[x].son[0]]+=Add[x];        }        if(T[x].son[1])        {            T[T[x].son[1]].key+=Add[x];            Add[T[x].son[1]]+=Add[x];        }        Add[x]=0;    }}inline int Newnode(int key, int fa) //新建一个节点并返回{    ++cnt;    T[cnt].key=key;    T[cnt].num=T[cnt].size=1;    T[cnt].fa=fa;    T[cnt].son[0]=T[cnt].son[1]=0;    return cnt;}inline void Rotate(int x, int p) //0左旋 1右旋{    int y=T[x].fa;    PushDown(y);    PushDown(x);    T[y].son[!p]=T[x].son[p];    T[T[x].son[p]].fa=y;    T[x].fa=T[y].fa;    if(T[x].fa)        T[T[x].fa].son[T[T[x].fa].son[1] == y]=x;    T[x].son[p]=y;    T[y].fa=x;    PushUp(y);    PushUp(x);}void Splay(int x, int To) //将x节点移动到To的子节点中{    while(T[x].fa != To)    {        if(T[T[x].fa].fa == To)            Rotate(x, T[T[x].fa].son[0] == x);        else        {            int y=T[x].fa, z=T[y].fa;            int p=(T[z].son[0] == y);            if(T[y].son[p] == x)                Rotate(x, !p), Rotate(x, p); //之字旋            else                Rotate(y, p), Rotate(x, p); //一字旋        }    }    if(To == 0) rt=x;}int GetPth(int p, int To) //返回第p小的节点 并移动到To的子节点中{    if(!rt || p > T[rt].size) return 0;    int x=rt;    while(x)    {        PushDown(x);        if(p >= T[T[x].son[0]].size+1 && p <= T[T[x].son[0]].size+T[x].num)            break;        if(p > T[T[x].son[0]].size+T[x].num)        {            p-=T[T[x].son[0]].size+T[x].num;            x=T[x].son[1];        }        else            x=T[x].son[0];    }    Splay(x, 0);    return x;}int Find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处{    if(!rt) return 0;    int x=rt;    while(x)    {        PushDown(x);        if(T[x].key == key) break;        x=T[x].son[key > T[x].key];    }    if(x) Splay(x, 0);    return x;}int Prev() //返回根节点的前驱 非重点{    if(!rt || !T[rt].son[0]) return 0;    int x=T[rt].son[0];    while(T[x].son[1])    {        PushDown(x);        x=T[x].son[1];    }    Splay(x, 0);    return x;}int Succ() //返回根结点的后继 非重点{    if(!rt || !T[rt].son[1]) return 0;    int x=T[rt].son[1];    while(T[x].son[0])    {        PushDown(x);        x=T[x].son[0];    }    Splay(x, 0);    return x;}void Insert(int key) //插入key值{    if(!rt)        rt=Newnode(key, 0);    else    {        int x=rt, y=0;        while(x)        {            PushDown(x);            y=x;            if(T[x].key == key)            {                T[x].num++;                T[x].size++;                break;            }            T[x].size++;            x=T[x].son[key > T[x].key];        }        if(!x)            x=T[y].son[key > T[y].key]=Newnode(key, y);        Splay(x, 0);    }}void Delete(int l, int r) //删除值在[l, r]中的节点{    if(!Find(l)) Insert(l), ans--;    int p=Prev();    if(!Find(r)) Insert(r), ans--;    int q=Succ();    if(!p && !q)    {        ans+=T[rt].size;        rt=0;        return;    }    if(!p)    {        ans+=T[T[rt].son[0]].size;        T[rt].son[0]=0;        PushUp(rt);        return;    }    if(!q)    {        Splay(p, 0);        ans+=T[T[rt].son[1]].size;        T[rt].son[1]=0;        PushUp(rt);        return;    }    Splay(p, q);    if(T[p].son[1])        ans+=T[T[p].son[1]].size;    T[p].son[1]=0;    PushUp(p);    PushUp(q);}int N, MIN, k;char ch;int main(){    scanf("%d %d", &N, &MIN);    while(N--)    {        scanf(" %c %d", &ch, &k);        switch (ch)        {            case 'I':                if(k >= MIN)                    Insert(k);                break;            case 'A':                T[rt].key+=k;                Add[rt]+=k;                break;            case 'S':                T[rt].key-=k;                Add[rt]-=k;                Delete(-INF, MIN-1);                break;            case 'F':                if(T[rt].size-k+1>0)                    printf("%d\n", T[GetPth(T[rt].size-k+1, 0)].key);                else                    printf("-1\n");        }    }    printf("%d\n", ans);    return 0;}
0 0