CF1329A Dreamoon Likes Coloring(贪心)

对于某一类构造题,我们先要找出不符合条件的情况输出-1

之后剩下的都是肯定有答案的

然后我们就开始做这道题目,首先一个想法我们肯定想保证如何不被覆盖

这样我们肯定是想每个点的涂的位置只向后移一位,这样至少一个位置不会被覆盖

但这样我们会发现有可能涂不满,因此我们再用新思路和他结合一下,我们会想到一个边界

如果在边界点上涂,后面就肯定有方案可以涂满,那么这么边界点就是后缀和,这也是最优的,因为跳到了边界。

因此我们从后往前看,当剩下要涂的空格大于i的时候,我们就涂后缀的位置,不然就涂i,因为要保证不被别的颜色覆盖,所以i也是一个边界点。

i这个边界点表示,如果我的后缀和已经小于我当前的位置,那么剩下的我就一位一位涂就好了。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int a[N];
ll s[N];
ll ans[N];
int main(){
    int n;
    int m;
    cin>>n>>m;
    int i;
    int flag=0;
    for(i=1;i<=m;i++){
        cin>>a[i];
        if(n-a[i]<i-1)
            flag=1;
    }
    for(i=m;i>=1;i--){
        s[i]=s[i+1]+a[i];
    }
    if(s[1]<n)
        flag=1;
    if(flag){
        cout<<-1<<endl;
        return 0;
    }
    for(i=1;i<=m;i++){
        ans[i]=max((ll)i,n-s[i]+1);
    }
    for(i=1;i<=m;i++)
        cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}
View Code

 

posted @ 2020-04-15 08:48  朝暮不思  阅读(150)  评论(0编辑  收藏  举报