zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Java+7入门经典 -1 简介
    优化算法动画演示Alec Radford's animations for optimization algorithms
    如何写科技论文How to write a technical paper
    开始学习深度学习和循环神经网络Some starting points for deep learning and RNNs
    用500行Julia代码开始深度学习之旅 Beginning deep learning with 500 lines of Julia
    用10张图来看机器学习Machine learning in 10 pictures
    ICLR 2013 International Conference on Learning Representations深度学习论文papers
    ICLR 2014 International Conference on Learning Representations深度学习论文papers
    卷积神经网络CNN(Convolutional Neural Networks)没有原理只有实现
    卷积神经网络Convolutional Neural Networks
  • 原文地址:https://www.cnblogs.com/Mathics/p/3978047.html
Copyright © 2011-2022 走看看