Bzoj1503--Noi2004郁闷的出纳员

treap乱搞一下

对于工资的加减不直接修改的点的值或打标记,而是维护一个外围的delta,这样维护也很方便

剩下删除和插入都是基本操作了

另: linux下rand()的返回值是1-2^31-1,虽然感觉没什么关系,交上去就会被卡T掉。。。取个模就过了

代码:

#include<bits/stdc++.h>
#define MAXN 100205
#define MAXM 3005
#define INF 1000000000
#define MOD 998244353
#define LL long long
using namespace std;

inline int read() {
    int ret=0,f=1;char c=getchar();
    while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
    while(c<='9'&&c>='0') {ret=ret*10+c-'0';c=getchar();}
    return ret*f;
}

int n,m,delta;

struct node{
    int son[2],s,v,r,par,sz;
}x[MAXN];
struct Treap{
    int L,R,root,away,cnt;
    void init() {
        L=0;R=1;root=MAXN-5;away=0;cnt=0;
        x[MAXN-5].r=INF;x[MAXN-5].v=INF;
    }
    
    inline void rotate(int num,int p) {
        int pa=x[num].par,t=x[num].sz;
        x[x[pa].par].son[x[x[pa].par].son[L]==pa?L:R]=num;
        x[num].sz=x[pa].sz;x[pa].sz-=t-x[x[num].son[p]].sz;
        x[pa].son[p^1]=x[num].son[p];if(x[num].son[p]) {x[x[num].son[p]].par=pa;}
        x[num].son[p]=pa;x[num].par=x[pa].par;x[pa].par=num;
    }
    
    void Insert(int v) {
        x[++cnt].v=v;x[cnt].r=rand()%1000007;x[cnt].s=1;x[cnt].sz=1;
        int now=root,pre;
        while(true) {
            if(v==x[now].v) {x[now].s++;x[now].sz++;cnt--;return;}
            pre=v<x[now].v?R:L;x[now].sz++;
            if(!x[now].son[pre]) {x[now].son[pre]=cnt;x[cnt].par=now;break;}
            now=x[now].son[pre];
        }
        now=cnt;
        while(true) {
            if(x[x[now].par].son[L]==now) pre=R;else pre=L;
            if(x[now].r>x[x[now].par].r) rotate(now,pre);
            else break;
        }
    }
    void Del(int num) {
        while(x[num].son[L]) rotate(x[num].son[L],R);
        int now=x[num].par,pre=x[x[num].par].son[L]==num?L:R;
        while(now) {x[now].sz-=x[num].sz;now=x[now].par;}
        away+=x[num].sz;x[x[num].par].son[pre]=0;
    }
    void Check(int v) {
        int now=root,ed;
        while(true) {
            while(x[now].son[R]) now=x[now].son[R];
            if(x[now].v<v) Del(now);
            else break;
            now=root;
        }
    }
    int Qurey(int k) {
        int now=root;
        if(k>x[root].sz) return -1;
        while(true) {
            if(x[x[now].son[L]].sz>=k-x[now].s&&x[x[now].son[L]].sz<k) return x[now].v;
            if(x[x[now].son[L]].sz<k) {k-=x[now].s+x[x[now].son[L]].sz;now=x[now].son[R];}
            else now=x[now].son[L];
            
        }
    }
    
    int Finish() {return away;}
};

int main() {
    srand(2333333);
    n=read();m=read();
    Treap p;char q[10];int k,ret;
    p.init();
    for(int i=1;i<=n;i++) {
        scanf("%s",q);k=read();
        if(q[0]=='I') if(k>=m) p.Insert(k+delta);
        if(q[0]=='A') delta-=k;
        if(q[0]=='S') {delta+=k;p.Check(m+delta);}
        if(q[0]=='F') {
            ret=p.Qurey(k);
            printf("%d
",ret-(ret==-1?0:delta));
        }
    }
    printf("%d
",p.Finish());
    return 0;
}
原文地址:https://www.cnblogs.com/ihopenot/p/5915078.html