其他分享
首页 > 其他分享> > 15届黑龙江省赛 B. Bills of Paradise —— 线段树

15届黑龙江省赛 B. Bills of Paradise —— 线段树

作者:互联网

This way

题意:

在这里插入图片描述

题解:

对于前三个都可以用权值线段树,对于R操作,我们可以直接在D操作删除的时候用一个优先队列来存有哪些数被删掉了。时间复杂度可以保证是因为每个数被加进来都需要一次操作,所以不会超过n次操作R。
线段树较为庞大,敲代码时应当更注意细节,例如在D操作的时候,return之前应当push_up

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const ll mod=999999999999;
const int N=1e6+5;
unsigned long long k1, k2;

unsigned long long xorShift128Plus() {
    unsigned long long k3 = k1, k4 = k2;
    k1 = k4;
    k3 ^= k3 << 23;
    k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
    return k2 + k4;
}

int n;
ll a[N],b[N];
int num[N*4];
ll sum[N*4];
void init(int l,int r,int root,int p){
    if(l==r){
        sum[root]+=b[l],num[root]++;
        return ;
    }
    int mid=l+r>>1;
    if(mid>=p)
        init(l,mid,root<<1,p);
    if(mid<p)
        init(mid+1,r,root<<1|1,p);
    sum[root]=sum[root<<1]+sum[root<<1|1];
    num[root]=num[root<<1]+num[root<<1|1];
}
priority_queue<ll,vector<ll>,greater<ll> >Q;
int q_F(int l,int r,int root,int ql,int qr){
    if(!num[root])return -1;
    if(l==r)return l;
    int mid=l+r>>1;
    if(l>=ql&&r<=qr){
        if(num[root<<1])return q_F(l,mid,root<<1,ql,qr);
        else return q_F(mid+1,r,root<<1|1,ql,qr);
    }
    //push_down(root);
    int ans=-1;
    if(mid>=ql)
        ans=q_F(l,mid,root<<1,ql,qr);
    if(mid<qr&&ans==-1)
        ans=q_F(mid+1,r,root<<1|1,ql,qr);
    return ans;
}
int up_D(int l,int r,int root,int ql,int qr){
    if(!num[root])return -1;
    if(l==r){
        num[root]--;
        sum[root]-=b[l];
        Q.push(b[l]);
        return 1;
    }
    int mid=l+r>>1;
    if(l>=ql&&r<=qr){
        int ans=-1;
        if(num[root<<1]){
            ans=up_D(l,mid,root<<1,ql,qr);            
            num[root]=num[root<<1]+num[root<<1|1];
            sum[root]=sum[root<<1]+sum[root<<1|1];
            return ans;
        }
        else{
            ans=up_D(mid+1,r,root<<1|1,ql,qr);            
            num[root]=num[root<<1]+num[root<<1|1];
            sum[root]=sum[root<<1]+sum[root<<1|1];
            return ans;
        }
    }
    //push_down(root);
    int ans=-1;
    if(mid>=ql)
        ans=up_D(l,mid,root<<1,ql,qr);
    if(mid<qr&&ans==-1)
        ans=up_D(mid+1,r,root<<1|1,ql,qr);
    num[root]=num[root<<1]+num[root<<1|1];
    sum[root]=sum[root<<1]+sum[root<<1|1];
    return ans;
}
ll q_C(int l,int r,int root,int ql,int qr){
    if(l>=ql&&r<=qr)
        return sum[root];
    int mid=l+r>>1;
    ll ans=0;
    if(mid>=ql)
        ans=q_C(l,mid,root<<1,ql,qr);
    if(mid<qr)
        ans+=q_C(mid+1,r,root<<1|1,ql,qr);
    return ans;
}
char s[2];
const ll inf=1e12;
void gen() {
    scanf("%d %llu %llu", &n, &k1, &k2);
    for (int i = 1; i <= n; i++) {
        a[i] = xorShift128Plus() %mod  + 1;
        b[i]=a[i];
    }
    sort(b+1,b+1+n);
    int all=unique(b+1,b+1+n)-b-1;
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(b+1,b+1+all,a[i])-b;
        init(1,all,1,a[i]);
    }
    int q;
    ll x;
    scanf("%d",&q);
    while(q--){
        scanf("%s%lld",s,&x);
        if(s[0]=='F'){
            int p=lower_bound(b+1,b+1+all,x)-b;
            if(p>all){
                printf("%lld\n",inf);
                continue;
            }
            int pos=q_F(1,all,1,p,all);
            if(pos==-1)printf("%lld\n",inf);
            else printf("%lld\n",b[pos]);
        }
        else if(s[0]=='D'){
            int p=lower_bound(b+1,b+1+all,x)-b;
            if(p>all)continue;
            up_D(1,all,1,p,all);
        }
        else if(s[0]=='C'){
            int p=upper_bound(b+1,b+1+all,x)-b-1;
            if(p==0)
                printf("0\n");
            else printf("%lld\n",q_C(1,all,1,1,p));
        }
        else {
            while(!Q.empty()&&Q.top()<=x){
                ll u=Q.top();Q.pop();
                int p=lower_bound(b+1,b+1+all,u)-b;
                init(1,all,1,p);
            }
        }
    }
}
int main()
{
    gen();
}

标签:15,int,ll,mid,long,Paradise,return,Bills,root
来源: https://blog.csdn.net/tianyizhicheng/article/details/111159685