Problem - H - CodeforcesProblem - H - Codeforces
题意:有一个由n个数组成的环,每个位置需要被涂成对应颜色,然后有一个方便的机器,这个机器可以涂连续个子区间 k,然后新涂成的颜色会覆盖之前涂成的颜色,问你需要能够涂正确的次数的最小数目,如果不能输出-1。
思路:首先因为是一个环状,所以我们可以扩大一下形成2*n数组,然后每次选区域只选n个区域所为环处理。然后对应这个题目,如果k是1的话那么无论怎么涂结果都是一样的,然后因为这个机器一定会涂k个区域,那么如果所有连续区间的长度小于k的区间那么一定是不能满足条件的,然后只要存在连续区间大于等于k,那么无论怎么涂都可以最后那个子区间重新覆盖得到。
那么可以处理环把长度超过k的子序列区间放到环的末尾,先处理环的头部,然后每次根据要涂的长度增加相应的sum,最后直接输出就可以了。
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#define ll long long
using namespace std;
const int N = 3000000 + 100;
int n, m, h;
ll s[N];
int main()
{
int t;
cin >> t;
while (t--)
{
scanf("%d%d%d", &n, &m, &h);
for (int i = 1; i <= n; i++)
{
scanf("%lld", &s[i]);
s[i + n] = s[i];
}
int flag = 0;
if (h == 1)
{
printf("%d\n", n);
continue;
}
int ii = n;
for (int i = 1; i <= 2 * n; i++) //寻找长度大于等于k的子序列位置
{
int j = i, time = 0;
while (s[i] == s[j])
{
j++;
time++;
}
i = j - 1;
if (time >= h)
{
flag = 1;
ii = j - 1;
break;
}
}
if (!flag)
{
printf("-1\n");
continue;
}
if (ii < n)//因为遍历是要从ii的前n个数开始遍历,所有如果ii<n要先+i保证前面有数
ii += n;
ll sum = 0;
for (int i = ii - n + 1; i < ii; i++)//直接模拟
{
if (s[i] == s[i + 1])
{
int k = 2;
int j = i + 2;
while (s[i] == s[j])
{
j++;
k++;
}
i = j - 1;
sum += (k + (h - 1)) / h;
// if(j>=n&&k<h)sum++;
}
else sum++;
}
printf("%lld\n", sum);
}
return 0;
}