宁波多校(三) G仓鼠的鸡蛋(线段树)

用线段树维护区间剩余的最大值,这样可以辅助二分,越左越好

对于用完k堆的,直接将他的值变为0即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=6e5+10;
struct node{
    int l,r;
    int cnt;
    int k;
}tr[N<<2];
int n,m,k;
int a[N];
void pushup(int u){
    tr[u].cnt=max(tr[u<<1].cnt,tr[u<<1|1].cnt);
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r,m,k};
    }
    else{
        tr[u]={l,r};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        pushup(u);
    }
}
void modify(int u,int x,int k){
    if(tr[u].l==tr[u].r){
        tr[u].cnt-=k;
        tr[u].k-=1;
        if(tr[u].k==0){
            tr[u].cnt=0;
        }
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(x<=mid)
        modify(u<<1,x,k);
    else{
        modify(u<<1|1,x,k);
    }
    pushup(u);
}
int query(int u,int x){
    if(tr[u].l==tr[u].r){
        return tr[u].l;
    }
    int mid=tr[u].r+tr[u].l>>1;
    int res=0;
    if(tr[u<<1].cnt>=x)
        res=query(u<<1,x);
    else{
        res=query(u<<1|1,x);
    }
    return res;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n>>m>>k;
        int i;
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        build(1,1,n);
        for(i=1;i<=n;i++){
            if(a[i]>tr[1].cnt){
                printf("-1\n");
                continue;
            }
            int x=query(1,a[i]);
            printf("%d\n",x);
            modify(1,x,a[i]);
        }
    }
    return 0;
}
View Code

 

posted @ 2020-07-07 23:06  朝暮不思  阅读(180)  评论(0编辑  收藏  举报