https://codeforces.com/contest/1672/problem/C
input
4
5
1 1 1 1 1
5
2 1 1 1 2
6
1 1 2 3 3 4
6
1 2 1 4 5 4
output
2
1
2
0
题意
给定长度为
n
n
n 的序列
a
a
a 中,通过
0
0
0 次或多次以下操作使得 序列中只出现
0
0
0 次或
1
1
1 次相邻两个数相等的情况
- 选定两个相邻的点位并将其同时赋值为 x x x ,形式上为:选定 i i i(小于n),使得 a i = a i + 1 = x a_i = a_{i+1} = x ai=ai+1=x, x x x 为任意取值
思路
我们发现,如果我们使用了一次操作,则选择的两个位置上就会变成相同的,即会贡献
1
1
1 对相等
我们尝试一些例子,如下图:
- {
1
,
1
,
1
1,1,1
1,1,1}
则直接修改 一次 即可
- {
1
,
1
,
1
,
1
1,1,1,1
1,1,1,1}
则也是修改 一次
可以手动模拟一下 { 1 , 1 , 1 , 1 , 1 1,1,1,1,1 1,1,1,1,1},则需要两次
会发现除了{ 1 , 1 , 1 1,1,1 1,1,1}比较特殊,其余都是 r − l − 1 r - l - 1 r−l−1 的次数
综上对于连续出现的可以这样子修改
但是对于不连续出现的,因为每次操作都会留下 1 1 1 对相等,则我们并不能分开处理每一批连续出现的数
所以实际上我们相当于通过操作将每片连在一起,即从最左边第一次出现相邻相等的数,一直链接到最右边相邻相等的数
如以下:
{
1
,
1
,
2
,
1
,
1
1,1,2,1,1
1,1,2,1,1}
{
1
,
1
,
2
,
3
,
1
,
1
1,1,2,3,1,1
1,1,2,3,1,1}
最后会发现答案的计算都为:
r
−
l
−
1
r - l - 1
r−l−1,最后记得对长度为3就特判一下,不然公式会计算为0
AC代码
c
n
t
cnt
cnt 为统计出现相邻相等的对数
l
、
r
l 、r
l、r 记录最左端和最右端
#include <bits/stdc++.h>
#define endl '\n'
#define AC return 0;
using namespace std;
//#define ll long long
//#define int long long
int a[200005];
void slove()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
int l = n,r = 1;
int cnt = 0;
for(int i = 2; i <= n; i++)
{
if(a[i] == a[i - 1])
{
l = min(l,i - 1);
r = max(r,i);
cnt++;
}
}
if(cnt < 2)
cout << 0 << endl;
else
{
int k = r - l - 1;
if(k == 1)
cout << 1 << endl;
else
cout << k - 1 << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin >> T; while(T--)
slove();
AC
}