• 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
  • 相关阅读:
    不测的秘密:精准测试之路----读书笔记(第二章)
    如何使用for循环连续的实例化多个对象!
    java如何在一个有序的数组类插入一个数!
    webstrom 常用快捷键
    如何使Label带有链接??此法感觉有点取巧!!!
    System.DateTime的一些格式
    如何解决”无法将类型为“System.DateTime”的对象强制转换为类型“System.String”。“
    如何解决“连接未关闭。 连接的当前状态为打开”问题
    c语言中 %p的含义
    什么情况下用递归?
  • 原文地址:https://www.cnblogs.com/luxiaoming/p/5149600.html
Copyright © 2020-2023  润新知