codeforces 589G:线段树+二分

离线做

先按照t[]建线段树,维护区间的有效天数以及可用时间

然后把t[]从小到达排序,记得记录t中元素在线段树中的位置

把询问按照d从小到大排序,依次考虑

由于按照d排序,所以当前询问肯定是d最短的,我们在t数组中找到大于当前d的第一个元素位置,把这之前的元素全部从线段树中删除,表示这些天数无效

因为当前d已经是最小,所以删除对后续不会有影响

二分一个天数,查找0~mid天一共的工作时间(工作时间=总可用时间-准备时间*有效天数)

#include"cstdio"
#include"queue"
#include"cmath"
#include"stack"
#include"iostream"
#include"algorithm"
#include"cstring"
#include"queue"
#include"map"
#include"set"
#include"vector"
#define ll long long
#define mems(a,b) memset(a,b,sizeof(a))
#define ls pos<<1
#define rs pos<<1|1

using namespace std;
const int MAXN = 200500;
const int MAXQ = 10050;
const int INF = 0x3f3f3f3f;

struct T{
    ll w;
    int id;
}t[MAXN];

struct Q{
    int d,r,id;
}q[MAXN];

struct Node{
    int l,r;
    int now;
    ll sum;
}node[MAXN<<2];

int ans[MAXN];
int n,m;

bool cmp(Q a,Q b){
    return a.d<b.d;
}

bool cmp1(T a,T b){
    return a.w<b.w;
}

void pushup(int pos){
    node[pos].sum=node[ls].sum+node[rs].sum;
    node[pos].now=node[ls].now+node[rs].now;
}

void build(int l,int r,int pos){
    node[pos].l=l;
    node[pos].r=r;
    if(l==r){
        node[pos].sum=t[l].w;
        node[pos].now=1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,ls);
    build(mid+1,r,rs);
    pushup(pos);
}

int get_pos(ll x){
    int low=0,high=m-1,mid,ans=m;
    while(low<=high){
        mid=(low+high)>>1;
        if(t[mid].w>x){
            ans=mid;
            high=mid-1;
        }
        else low=mid+1;
    }
    return ans;
}

void del(int p,int pos){
    if(node[pos].l==p&&node[pos].r==p){
        node[pos].sum=0;
        node[pos].now=0;
        return;
    }
    int mid=(node[pos].l+node[pos].r)>>1;
    if(p<=mid) del(p,ls);
    else del(p,rs);
    pushup(pos);
}
ll query(int l,int r,int pos,int D){
    ll ans=0;
    if(l<=node[pos].l&&node[pos].r<=r){
        return node[pos].sum-(ll)node[pos].now*D;
    }
    int mid=(node[pos].r+node[pos].l)>>1;
    if(l<=mid) ans+=query(l,r,ls,D);
    if(r>mid) ans+=query(l,r,rs,D);
    return ans;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        scanf("%I64d",&t[i].w);
        t[i].id=i;
    }

    build(0,m-1,1);
    sort(t,t+m,cmp1);

    for(int i=0;i<n;i++){
        scanf("%d%d",&q[i].d,&q[i].r);
        q[i].id=i;
    }
    sort(q,q+n,cmp);

    int j=0;
    for(int i=0;i<n;i++){
        int pos=get_pos((ll)q[i].d);
        for(;j<pos;j++) del(t[j].id,1);

        if(node[1].sum-q[i].d*node[1].now<q[i].r){
            ans[q[i].id]=0;
            continue;
        }
        int low=0,high=m-1,mid,t;
        while(low<=high){
            mid=(low+high)>>1;
            ll a=query(0,mid,1,q[i].d);
            if(a>=q[i].r){
                t=mid+1;
                high=mid-1;
            }
            else low=mid+1;
        }
        ans[q[i].id]=t;
    }
    for(int i=0;i<n;i++) printf("%d ",ans[i]);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/luxiaoming/p/5149600.html