• 「JXOI2017」加法


    题目描述

    可怜有一个长度为 $n$ 的正整数序列 $A$ ,但是她觉得 $A$ 中的数字太小了,这让她很不开心。
    于是她选择了 $m$ 个区间 $[l_i , r_i]$ 和两个正整数 $a$ , $k$ 。她打算从这 $m$ 个区间里选出恰好 $k$ 个区间,并对每个区间执行一次区间加 $a$ 的操作。
    (每个区间最多只能选择一次。)

    对区间 $[l, r]$ 进行一次加 $a$ 操作可以定义为对于所有 $i in [l, r]$ ,将 $A_i$ 变成 $A_i + a$ 。
    现在可怜想要知道怎么选择区间才能让操作后的序列的最小值尽可能的大,即最大化 $min { A_i }$ 。

    数据范围

    $sum n leq 2 imes 10^5,sum m leq 2 imes 10^5$

    题解

    看到最小值最大化首先想到二分答案,然后贪心。

    从 $1$ 到 $n$ 考虑每个 $a_i$ 能否达到 $mid$ 。如果没有达到的话,我们可以选择一些区间使它变大。

    那我们应该选择怎样的区间呢?不难发现应该选择右端点更远的区间,这样对后面的 $a$ 来说更容易达到 $mid$

    所以我们可以把区间按照左端点排序,进行 $two-pointer$ ,用堆维护右端点即可。

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=2e5+5;
    int T,n,m,k;
    LL f[N],in,a,s[N];
    struct O{int l,r;}p[N];
    bool cmp(O A,O B){return A.l<B.l;}
    bool J(LL x){
        priority_queue<int>q;
        for (int i=1;i<=n;i++) s[i]=f[i]-f[i-1];
        for (int j=1,r,i=1,l=0;i<=n;i++){
            while(j<=m && p[j].l<=i) q.push(p[j++].r);
            s[i]+=s[i-1];
            while(!q.empty() && s[i]<x && l<k){
                r=q.top();q.pop();
                if (r<i) break;
                s[i]+=a;l++;s[r+1]-=a;
            }
            if (s[i]<x) return 0;
        }
        return 1;
    }
    void work(){
        scanf("%d%d%d%lld",&n,&m,&k,&a);in=2e18;
        for (int i=1;i<=n;i++)
            scanf("%lld",&f[i]),in=min(f[i],in);
        for (int i=1;i<=m;i++)
            scanf("%d%d",&p[i].l,&p[i].r);
        sort(p+1,p+m+1,cmp);
        LL l=in,r=in+a*k,mid;
        while(l<r){
            mid=(l+r+1)>>1;
            if (J(mid)) l=mid;
            else r=mid-1;
        }
        printf("%lld
    ",l);
    }
    int main(){
        for (scanf("%d",&T);T--;work());
        return 0;
    }
  • 相关阅读:
    记录犯得最可笑的错误
    爬虫阶段内容总结
    docker_nginx_Elasticsearch
    git基础
    爬虫pearPro
    爬虫wangyiPro
    sunPro
    docker-compose终极搞定个人博客
    小程序下拉三个小点不显示问题
    vue鼠标拖动
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11778977.html
Copyright © 2020-2023  润新知