Codeforces 631 (Div. 2) C. Dreamoon Likes Coloring 思维or构造

https://codeforces.com/contest/1330/problem/C
给n个格子染色,有m种颜色,要求最后的所以格子被染色,并且有m种颜色。
染色要求:每种颜色有一个值li,选择 [1,n-li+1] 范围的一个数pi,把 [pi,pi+li-1] 范围内的格子染色,不能超过n,否则无法染色,重复染色的格子的颜色以最后染色的颜色为准。
求:pi,如果不能满足条件,则打印 -1 .
人话:对于每个li,从任意起点开始把li个格子染色,不能染出n个格子的范围,找到每个起始位置,使得所有格子都被染色,并且有m种颜色。

思路:首先输入li的前缀和必须满足大于等于n,每次染色,后面有足够的格子,否则输出 -1 ,那么我们先从后往前维护每次染色的起点的最大值,然后从前往后染色,每次尽量染最多的格子,前一个染色结束位置的后面一个位置和起点的最大位置取min,这样就保证了它能够染li个格子并且不会超出n,也不会因为重复染色过多而导致某种颜色被覆盖或者还有格子没有被染色。

#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
const int mod=1e9+7;
typedef long long ll;
//typedef __int128 LL;
const int inf=0x3f3f3f3f;
const long long INF=0x3f3f3f3f3f3f3f3f;
int ans[MAXN],t[MAXN];
int a[MAXN];

int main()
{
    int n,m;
    ll sum=0;
   
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&a[i]);
        sum+=a[i];
    }
  
    if(sum<n)printf("-1
");
    else
    {
        int l=inf;
        for(int i=m;i>=1;i--)
        {
            l=min(l,n-a[i]+1);
            t[i]=l;
            l--;
        }
        if(l<0)printf("-1
");
        else
        {
            l=1;
            for(int i=1;i<=m;i++)
            {
                l=min(l,t[i]);
                ans[i]=l;
                l=l+a[i];                       
            }
            for(int i=1;i<=m;i++)printf("%d%c",ans[i],i==m?'
':' ');
        }
    }
    return 0;
}
/*
100 3
60 20 20

5 4
2 2 2 2

*/
原文地址:https://www.cnblogs.com/MZRONG/p/12642578.html