[NOI2004]郁闷的出纳员(到底是谁郁闷啊?)

一道 FHQ treap 的裸水题,卡了这么久。(咦~一看就是修为不够

 

题解什么的,不用看的(话说那我为什么要写这篇题解咧...),直接 FHQ 模板腾上去就能秒 A 了(打脸)

 

谈谈 debug ...  首先是一个 0 写成了 1 ,GG ,然后是 m-1 出现了乱七八糟的东西,然后又被误导在 insert 操作不执行时 ++res ... 等,以上

咦~这个人一看就是菜鸡这么裸的题都要 debug 这么久)(*/ω\*)

 

所以就是 要套 FHQ 里面的merge 、split_key、split_val、get_rank、ins (以及一些update 、pushdown、rand 什么零碎操作)

如果你还不是很了解 FHQ treap ,可以看这里

然后这题的增减工资其实可以打一下懒标记的啦~(一开始没搞清楚状况没用懒标记直接对 m 进行操作,后来发现这个增减工资只对操作前存在的员工有用啊!),

split 的时候 pushdown 一下就好了(merge 是不用的,因为这里没有直接merge的操作,都是先split完了之后才merge的)

 

所以...上代码...

 

//by Judge
#include<iostream>
#include<cstdio>
using namespace std;
const int M=2e5+111;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){
    int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
}
inline int cread(){
    char c=getchar();
    while(!isupper(c)) c=getchar();
    switch(c){
        case 'I': return 1;
        case 'A': return 2;
        case 'S': return 3;
        case 'F': return 4;
    }
}
char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(int x){
    if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='
';
}
int n,m,q,res,cnt,root;
struct Node { int val,key,siz,tag,ch[2]; } t[M];
inline int Rand() { static int seed=998; return seed=int(seed*48271LL%(~0u>>1)); }
inline void update(int now){ t[now].siz=t[t[now].ch[0]].siz+t[t[now].ch[1]].siz+1; }
inline void pushdown(int now){ //多了pushdown
    t[t[now].ch[0]].val+=t[now].tag,t[t[now].ch[1]].val+=t[now].tag,
    t[t[now].ch[0]].tag+=t[now].tag,t[t[now].ch[1]].tag+=t[now].tag,t[now].tag=0;
}
int merge(int u,int v) {
    if(!u || !v) return u|v;
    if(t[u].key<t[v].key) { t[u].ch[1]=merge(t[u].ch[1],v),update(u); return u; }
    else { t[v].ch[0]=merge(u,t[v].ch[0]),update(v); return v; }
}
void split_val(int now,int k,int& x,int& y) {
    if(!now) return (void)(x=y=0); pushdown(now);
    if(t[now].val<=k) split_val(t[x=now].ch[1],k,t[now].ch[1],y);
    else split_val(t[y=now].ch[0],k,x,t[now].ch[0]); update(now);
}
void split_k(int now,int k,int& x,int& y) {
    if(!now) return (void)(x=y=0); pushdown(now);
    if(t[t[now].ch[0]].siz>=k) split_k(t[y=now].ch[0],k,x,t[now].ch[0]),update(now);
    else split_k(t[x=now].ch[1],k-t[t[now].ch[0]].siz-1,t[now].ch[1],y),update(now);
}
inline void ins(int x) { int u,a,b; t[u=++cnt].key=Rand(),t[u].val=x,t[u].siz=1,split_val(root,x,a,b),root=merge(merge(a,u),b); }
inline int get_val(int x) { int a,b,c,d,e; split_k(root,x-1,a,b),split_k(b,1,c,d),e=t[c].val,root=merge(a,merge(c,d)); return e; }
signed main() {
    n=read(),m=read()-1;
    for(int opt,x;n;--n){
        opt=cread(),x=read();
        switch(opt){ //四个较为常规的操作
            case 1: if(x>m) ins(x); break;
            case 2: t[root].val+=x,t[root].tag+=x; break;
            case 3: t[root].val-=x,t[root].tag-=x,split_val(root,m,x,root),res+=t[x].siz; break;
            case 4: print(x>t[root].siz?-1:get_val(t[root].siz-x+1)); break;
        } Ot();
    } print(res),Ot(); return 0;
}

 

原文地址:https://www.cnblogs.com/Judge/p/9539271.html