• [NOI2004]郁闷的出纳员


    平衡树,裸题。
    我们维护一下加法标记,然后剩下的就乱搞搞就好了。
    这里使用了(splay)实现。

    My Code:

    #include <bits/stdc++.h>
    #define il inline
    const int maxn = 1e5 + 10;
    const int inf = 0x3f3f3f3f;
    using namespace std;
    int n,m,i,j,k,root,add,tot,q,x,mn,padd,pnow;                
    int fa[maxn],ch[maxn][2],val[maxn],size[maxn],cnt[maxn];                        
    il void push_up(int o) {
        size[o] = size[ch[o][0]] + size[ch[o][1]] + cnt[o];
        return;
    }      
    il int which(int o) {
        return ch[fa[o]][1] == o;  
    }      
    il void clear(int o) {
        ch[o][0] = ch[o][1] = 0;    
        fa[o] = size[o] = cnt[o] = val[o] = 0;
        return;
    }   
    il void rotate(int o) {
        int f = fa[o],gf = fa[f],whi = which(o);         
        ch[f][whi] = ch[o][whi ^ 1];                
        fa[ch[f][whi]] = f;    
        ch[o][whi ^ 1] = f;                    
        fa[f] = o;fa[o] = gf;
        if(gf) ch[gf][ch[gf][1] == f] = o;        
        push_up(f);push_up(o);
        return;
    }
    il void splay(int o,int goal) {
        for(int f;(f = fa[o]) != goal;rotate(o)) {
            if(fa[f] != goal) rotate(which(f) == which(o) ? f : o);
        }
        if(!goal) root = o;  
        return;
    }                                                            
    il void insert(int v) {
        if(!root) {
            val[++tot] = v;cnt[tot] = 1;push_up(tot);                           
            root = 1;return;
        }
        int now = root,f = 0;
        while(1) {
            if(val[now] == v) {
                ++cnt[now];
                push_up(now);push_up(f);
                splay(now,0);return;      
            }
            f = now,now = ch[now][val[now] < v];      
            if(!now) {
                val[++tot] = v;cnt[tot] = 1;
                ch[f][val[f] < v] = tot;fa[tot] = f;             
                push_up(tot);push_up(f);          
                splay(tot,0);return;
            }
        }
    }      
    il int get_rank(int k) {
        int now = root,res = 0;
        while(1) {
            if(k < val[now]) {
                now = ch[now][0];
            } else {
                res += size[ch[now][0]];          
                if(k == val[now]) {splay(now,0);return res + 1;}        
                res += cnt[now];
                now = ch[now][1];
            }
        }
    }                                
    il int get_kth(int k) {
        int now = root;   
        while(1) {
            if(ch[now][0] && k <= size[ch[now][0]]) {
                now = ch[now][0];
            } else {
                k -= size[ch[now][0]] + cnt[now];if(k <= 0) return val[now];         
                now = ch[now][1];		
            }
        }
    }
    il int get_id(int k) {
        int now = root;
        while(1) {
            if(k < val[now]) {
                now = ch[now][0];
            } else {
                if(k == val[now]) return now; 
                now = ch[now][1];
            }
        }
    }    
    il int get_prev() {
        int now = ch[root][0];   
        while(ch[now][1]) now = ch[now][1];
        return now;
    }
    il int get_succ() {
        int now = ch[root][1];   
        while(ch[now][0]) now = ch[now][0];
        return now; 
    }   
    il void erase(int k) {
        get_rank(k);if(cnt[root] > 1) {--cnt[root];return;}    
        if(!ch[root][0] && !ch[root][1]) {
            clear(root);root = 0;return;
        } 
        if(!ch[root][0]) {
            int tmp = root;
            root = ch[root][1];                  
            fa[root] = 0;    
            clear(tmp);
            return;		
        }     
        if(!ch[root][1]) {
            int tmp = root;
            root = ch[root][0];
            fa[root] = 0;
            clear(tmp);
            return;
        } 
        int x = get_prev(),tmp = root;         
        splay(x,0);      
        ch[x][1] = ch[tmp][1];
        fa[ch[x][1]] = x;                  
        clear(tmp);      
        push_up(root);  
        return;       
    }
    int main() {
        scanf("%d %d",&q,&mn);      
        insert(-inf);insert(inf); 
        while(q--) {
            char opt[2];int x;scanf("%s%d",opt,&x);
            switch(opt[0]) {
                case 'I': if(x < mn) continue;insert(x - add);++padd;break; 
                case 'A': add += x;break;
                case 'S': {
                    add -= x;
                    insert(mn - add);                 
                    int x = get_id(-inf),y = get_id(mn - add);    
                    splay(x,0);splay(y,x);           
                    int pos = ch[x][1];
                    ch[pos][0] = 0;
                    erase(mn - add);       
                    break;
                }  
                case 'F': {
                    pnow = get_rank(inf) - 2;if(pnow < x) {puts("-1");break;}   
                    printf("%d
    ",get_kth(pnow + 2 - x) + add);
                    break;
                }
            }
        }
        pnow = get_rank(inf) - 2;
        printf("%d
    ",padd - pnow);
        return 0;
    } 
    
    
  • 相关阅读:
    [转]Oracle 语法之 OVER (PARTITION BY ..) 及开窗函数
    oracle本月、上月、去年
    Oracle 物理视图刷新报错ORA-00942
    [转]Oracle trunc()函数的用法
    [转]物化视图创建 及 刷新机制修改
    [转]oracle制定定时任务(dbms_jobs)
    【转】Windows平台下的Subversion安装配置新手指南
    【转】数字签名与数字证书
    [转]SQL 常用函数及示例
    【转】视图、索引、存储过程 、触发器、游标及事务
  • 原文地址:https://www.cnblogs.com/Sai0511/p/10459215.html
Copyright © 2020-2023  润新知