• 【BZOJ 1503】[NOI2004]郁闷的出纳员


    【链接】 我是链接,点我呀:)
    【题意】

    在这里输入题意

    【题解】

    因为所有人工资同时递减。 所以可以设置一个变化值delta. 然后每个人的初始值为k 则把k-delta加入伸展树中。 会发现delta变化之后。 伸展树中每个人的工资就仍然是原先的值+delta

    比如
    I 2000
    delta = 100
    则会插入一个1900到伸展树中。

    然后delta的值可能会发生变化。

    但会发现1900+delta会总是和这个人的当前工资相同
    (并且对于每个人都是如此

    那么我们只要把min-delta插入到伸展树种。
    则比他小的数字都是要离开的人
    (把这个min-delta移动到根节点。
    然后把它的左子树大小累加一下就好

    至于找第k大。
    则也是伸展树能够完成的事情。

    x-delta插入
    以及delta改变之后
    x+delta始终是每个人的真实工资这一点很关键。
    (很棒的ideal

    【代码】

    #include <cstdio>
    #define which(x) (ch[fa[x]][1]==x)
    using namespace std;
    
    int n,mi,delta;
    
    const int N = 1e5 + 200;
    
    int m,fa[N], tot, ch[N][2], root, x, siz[N],value[N];
    
    void push_up(int x)
    {
        siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
    }
    
    int Rank(int x, int k)
    {
        if (siz[ch[x][0]] >= k)
            return Rank(ch[x][0], k);
        else
            if (k == siz[ch[x][0]] + 1)
                return x;
            else
                return Rank(ch[x][1], k - siz[ch[x][0]] - 1);
    }
    
    void Rotate(int x)
    {
        int f = fa[x];
        bool k = which(x);
        ch[f][k] = ch[x][!k];
        ch[x][!k] = f;
        ch[fa[f]][which(f)] = x;
        fa[ch[f][k]] = f;
        fa[x] = fa[f];
        fa[f] = x;
        siz[x] = siz[f];
        push_up(f);
    }
    
    void Splay(int x, int g)
    {
        while (fa[x] != g)
        {
            int f = fa[x];
            if (fa[f] == g)
            {
                Rotate(x);
                break;
            }
            if (which(x) ^ which(f))
                Rotate(x);
            else
                Rotate(f);
            Rotate(x);
        }
        if (!g) root = x;
    }
    
    void cr(int x,int num)
    {
        if (!x){
            root = ++tot;
            siz[tot] = 1;
            value[tot] = num;
            return;
        }
        if (ch[x][num>value[x]]==0){
            ch[x][num>value[x]] = ++tot;
            value[tot] = num;
            fa[tot] = x;
            siz[tot] = 1;
        }else
            cr(ch[x][num>value[x]],num);
        push_up(x);
    }
    
    
    int main()
    {
        //freopen("D:\rush.txt","r",stdin);
        long long ans = 0;
    
        scanf("%d%d",&n,&mi);
        for (int i = 1;i <= n;i++){
            int k;
            char s[5];
            scanf("%s",s);
            if (s[0]=='I'){
                scanf("%d",&k);
                if (k<mi) continue;
                cr(root,k-delta);
                Splay(tot,0);
            }else if (s[0]=='A'){
                scanf("%d",&k);
                delta+=k;
            }else if (s[0]=='S'){
                scanf("%d",&k);
                delta-=k;
                cr(root,mi-delta);
                Splay(tot,0);
                ans+=siz[ch[tot][0]];
                root = ch[tot][1];
                fa[root] = 0;
            }else if (s[0]=='F'){
                scanf("%d",&k);
                if (k>siz[root]){
                    printf("%d
    ",-1);
                }else{
                    int x = Rank(root,siz[root]-k+1);
                    Splay(x,0);
                    printf("%d
    ",value[x]+delta);
                }
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    HDU 5710 digit sum
    Fibonacci Tree HDU
    2016CCPC东北赛补题
    紫书水题
    20180415校赛
    随心所欲小游戏
    Alpha版本测试报告
    第四天作业
    第二天作业
    第一天作业
  • 原文地址:https://www.cnblogs.com/AWCXV/p/8661727.html
Copyright © 2020-2023  润新知