• NOI2004 郁闷的出纳员


    往事不堪回首。。

    这个题目花了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注意。

    #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 100005
    
    using 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
    ", T[GetPth(T[rt].size-k+1, 0)].key);
                    else
                        printf("-1
    ");
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    MySQL常用函数
    SQL之join
    java并发编程之三--CyclicBarrier的使用
    java并发编程之二--CountDownLatch的使用
    java并发编程之一--Semaphore的使用
    微信小程序 bindcontroltap 绑定 没生效
    报错:Syntax error on tokens, delete these tokens
    java创建类的5种方式
    数据类型转换
    JS数据结构算法---数组的算法
  • 原文地址:https://www.cnblogs.com/Mathics/p/3978047.html
Copyright © 2020-2023  润新知