题目出处
High Load Database Gym – 102411H
ICPC 2019-2020 North-Western Russia Regional Contest

原文

题意

给长度为n的整数序列。
询问q次, 每次给定一个整数t, 你要把给定的序列尽可能少的划分, 要求每部分的区间和不大于t.
最终输出最少划分区间的数目。

思路

这道题是很明显的前缀和+二分的题目。

因为涉及到区间和, 所以不难想到利用前缀和进行O(1)的化简。

而二分的地方在于:

  • 这个区间要么是不可能的
    即区间中的最大元素比给定的t大.

  • 除此之外的情况就是可以二分的了;
    因为这个区间一定被划分成1-n份, n份一定是可行的. 在对于区间[l, r]划分时, 我们希望尽可能的靠右去划分(因为要保证分割尽可能少), 所以直接套二分模板, 每次改变被划分的区间即可.

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define int long long
const int N=2e6+10;
int a[N];
int ans[N];
int prefix[N];
int n,m;
int solve(int x)
{
    if(ans[x]) return ans[x];
    int step=0;
    int last=1;
    while(last<=n)
    {
        int pos=upper_bound(prefix+1,prefix+n+1,x+prefix[last-1])-prefix;//找出第一个大于等于last的数
        //cout<<pos<<"-->"<<endl;
        last=pos;
        step++;
    }
    return ans[x]=step;
}
signed main()
{
    scanf("%lld",&n);
    int maxx=-1;
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]),maxx=max(maxx,a[i]);
    for(int i=1;i<=n;i++) prefix[i]=prefix[i-1]+a[i];
    scanf("%lld",&m);
    while(m--)
    {
        int x;
        scanf("%lld",&x);
        if(x<maxx) printf("Impossible\n");
        else printf("%lld\n",solve(x));
    }
    return 0;
}

原文地址:http://www.cnblogs.com/kingwz/p/16814689.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性