CF-Round #631-div2-C题&div1-A
C. Dreamoon Likes Coloring
这道题也是div1的A题。
这道题是一道贪心题。
这道题我写了很久。第一题目不能理解,第二贪心策略理解不到位。
最后理解之后的那一刻就真的拍桌子欢呼了。。(没有夸张)
题目是一个涂色。给了你m种颜色。要求m种颜色在最后效果中必须出现并且没有未涂色的格子。
然后给出涂色的一个特定区间l[]。
让你构造一个序列q[]满足上述要求。
每次涂色需要涂区间q[i] ~ q[i] + l[i] - 1的部分;最终格子的颜色以最后涂上的颜色为准。
就是那个给定的区间那里我就很迷。。特别是范围部分。。。真的迷。要求q[i] + l[i] - 1不能大于n了。
也就是说q[i]本来就是有范围要求的了。
有两种情况很明显需要特判不满足要求的:
1.如果l[]的总和sum都小于n的话,说明就算我们分散的涂颜色。但最后还是有格子没有涂上,不能涂满所有的格子。
第二个特判后面再说。
很显然,我们构造出来的第一个p[1] = 1;(肯定要从第一个格子开始啦)
并且为了不让后面涂色的区间完全覆盖前面涂色的区间:我们有:
p[i + 1] > p[i];这个也很明显把。
比如p[2] > p[1] = 1;也就是说p[2] >= 2;
p[3] > p[2] >= 2; p[3] >= 3;
所以我们可以得到p[i] >= i; 就是需要不小于当前的下标。
再来说一下第二种特判情况:
我们根据上面可以得到p[i] >= i;
不妨让p[i]取最小值i;
那么当前涂色区间为:i + l[i] - 1;
那么如果i + l[i] - 1 > n的话(最小值都大于n了)肯定没有满足要求的序列了。输出-1即可。
贪心策略:尽可能让前面的涂色区域小,给后面的涂色区域留更大的空间。
再看求p[m]的时候。我们既要求不能让p[m] + l[m] - 1不能超过n,也不能让p[m] + l[m] - 1 小于n(因为按照前面说的贪心策略)。所以只能让p[m] + l[m] - 1 = n;
我们得到式子p[m] = n - l[m] + 1;
再考虑:要使得没有空格子,也就是每个格子都需要涂上颜色。
考虑p[i]和p[i + 1]的关系。
当涂到第i种颜色时区域:p[i] ~ p[i] + l[i] - 1;
所以p[i + 1]最大应该都是p[i] + l[i](这种恰好跟上一个颜色衔接的情况)
所以我们得到另外一个式子:
p[i + 1] <= p[i] + l[i];
移项得:
p[i] >= p[i + 1] - l[i];
通过这个式子我们枚举一下:
p[i] >= p[i + 1] - l[i];
p[i + 1] >= p[i + 2] - l[i + 1];
p[i + 2] >= p[i + 3] - l[i + 2];
…
…
…
p[m-1] >= p[m] - l[m - 1];
我们把不等式左边的相加,不等式右边的相加。消项;
得到:
p[i] >= p[m] - l[i] - l[i + 1] - l[i + 2] - l[m - 1];
我们再把上面得到的式子p[m] = n - l[m] + 1代入上式:
得到p[i] >= n - suf[i] + 1;其中suf[i]表示i的后缀和。
然后还有上面得到的式子p[i] >= i;
两个式子都要满足。我们取一下最大值就行。我们的贪心策略是尽可能取小嘛。所以
p[i] = max(i, n - suf[i] + 1);
维护一下~
完成啦~(开心)
理解了之后就很好解决了,主要是特判的情况要考虑到位。
最后要开ll,不然会wa.
代码部分:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
ll n, m;
ll l[N];
int flag;
ll sum;
ll suf[N];
int main()
{
cin >> n >> m;
for (ll i = 1; i <= m; i++)
{
cin >> l[i];
sum += l[i];
if (l[i] + i - 1 > n)
{
flag = 1;
}
}
if (flag || sum < n)
{
cout << "-1\n";
}
else
{
suf[m] = l[m];
for (ll i = m - 1; i >= 1; i--)
{
suf[i] = suf[i + 1] + l[i];
}
for (ll i = 1; i <= m; i++)
{
cout << max(i, n - suf[i] + 1) << " ";
}
cout << endl;
}
return 0;
}