[题解]luogu_P1486郁闷的出纳员(权值线段树

时间:2019-09-26
本文章向大家介绍[题解]luogu_P1486郁闷的出纳员(权值线段树,主要包括[题解]luogu_P1486郁闷的出纳员(权值线段树使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一眼权值线段树因为不会写平衡树线段树还好写啊

然后死咗

才发现后来的人不会被前面操作影响

于是维护一个历史记录,每次插入的时候减去delta因为查询出来要加上delta,常用操作

然而调了一万年

#include<bits/stdc++.h>
#define ls (x<<1)
#define rs (x<<1|1)
#define mid ((l+r)>>1)
using namespace std;
const int maxm=400009;
const int base=200000;
int n,m,lmt,ans,delta;
int t[maxm<<2],tg[maxm<<2];
inline void pd(int x){
    if(tg[x]){
        tg[ls]=tg[rs]=1;
        t[ls]=t[rs]=0;
        tg[x]=0;
    }
}
void insert(int x,int l,int r,int pos){
//    if(pos==200080)cout<<l<<' '<<r<<endl;
    if(l==r){
        t[x]++;
        return;
    }
    pd(x);
    if(pos<=mid)insert(ls,l,mid,pos);
    else insert(rs,mid+1,r,pos);
    t[x]=t[ls]+t[rs];
}
void del(int x,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        ans+=t[x];
        t[x]=0;tg[x]=1;
//        cout<<'$'<<l<<' '<<r<<endl;
        return;
    }
    pd(x);
    if(L<=mid)del(ls,l,mid,L,R);
    if(R>mid)del(rs,mid+1,r,L,R);
    t[x]=t[ls]+t[rs];
}
int query(int x,int l,int r,int k){
    if(l==r)return l;
    pd(x);
    if(k>t[rs])return query(ls,l,mid,k-t[rs]);
    else return query(rs,mid+1,r,k);
}
int main(){
    scanf("%d%d",&n,&lmt);char s[5];
    for(int i=1,k;i<=n;i++){
        scanf("%s",s);
        scanf("%d",&k);
        if(s[0]=='I'){
            if(k>=lmt)insert(1,0,400000,k-delta+base);
        }
        else if(s[0]=='A'){
//            lmt-=k;
            delta+=k;
        }
        else if(s[0]=='S'){
//            lmt+=k;
            delta-=k;
//            cout<<'#'<<lmt<<endl;
            del(1,1,400000,0,lmt-1-delta+base);
//            cout<<'#'<<t[1]<<endl;
        }
        else{
            if(k>t[1])printf("-1\n");
            else printf("%d\n",query(1,1,400000,k)+delta-base);
        }
    }
    printf("%d",ans);
}

原文地址:https://www.cnblogs.com/superminivan/p/11592235.html