2022-03-27每日刷题打卡
代码源——每日一题
数组操作 - 题目 - Daimayuan Online Judge
给你一个有 n 个元素的数组 a 。你可以对它进行如下操作,次数不限。
从一个偶数大小为 2k 的数组中选择一些从位置 l 开始的子数组(1≤l≤l+2⋅k−1≤n1≤l≤l+2⋅k−1≤n, k≥1k≥1) ,对于 0 到 k-1(包括)之间的每一个 i ,将值 al+k+i 分配给 al+i 。
例如,如果 a=[2,1,3,4,5,3] ,然后选择 l=1 和 k=2 ,应用这个操作,数组将变成 a=[3,4,3,4,5,3]。
请找出使数组中所有元素相等所需的最少操作数(可能是零)。
输入格式
输入由多个测试案例组成。第一行包含一个整数 t(1≤t≤2⋅104)–测试案例的数量。测试用例的描述如下。
每个测试用例的第一行包含一个整数 n(1≤n≤2⋅10^5 )–数组的长度。
每个测试用例的第二行包含 n 个整数 a1,a2,…,an(1≤ai≤n)–数组的元素a。
输出格式
打印 t 行,每行包含相应测试案例的答案–用给定的操作使数组中所有元素相等所需的最小操作数。
样例输入
5
3
1 1 1
2
2 1
5
4 4 4 2 4
4
4 2 1 3
1
1
样例输出
0
1
1
2
0
数据规模
保证所有测试用例的 n 之和不超过 2⋅10^5。
提示
在第一个测试中,所有元素都是相等的,因此不需要任何操作。
在第二个测试中,你可以应用一个操作,k=1,l=1,设置 a1:=a2 ,通过1个操作,数组变成[1,1]。
在第三个测试中,你可以应用一个操作,k=1,l=4,设置 a4:=a5 ,然后数组变成[4,4,4,4,4]。
在第四个测试中,你可以应用一个操作,k=1,l=3,设置 a3:=a4 ,数组变成[4,2,3,3],然后你可以应用另一个操作,k=2,l=1,设置a1:=a3, a2:=a4,数组变成[3,3,3,3]。
在第五次测试中,只有一个元素,因此不需要任何操作。
可能题目看着有点懵,其实就是每次可以把后面一个区间的数,赋值给后面相距k个位置的区间,然后我们要把整个数组改成一样的。
首先我们就可以知道了,要想数组一样,只能是改成全部和最后一个数一样,因为只能通过后面的数来修改前面的数,所以要想数组一样只能是吧整个数组改成最后一个的样子。
我们就从后面开始遍历,记录所有和最后一个数相同的个数,记作ans,在此过程种,一旦遇到和最后一个不一样的,我们就直接把这个数改成一样的,修改次数++,但一个个修改太麻烦了,我们可以直接把后面的ans个相同的数赋给前面的ans个数,这样整个数组就有ans*2个位置都是相同的数了(也不用管赋值前的数是什么样,如果是和最后一样也没影响,如果不一样那就正好改成一样的)。最后输出修改次数就行。
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 110;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
vector<int>v(n);
for (int i = n-1; i >=0 ; i--)
cin >> v[i];
int num = v[0], res = 0, ans = 1;
while (ans < n)
{
if (v[ans] == num)ans++;
else
{
res++;
ans *= 2;
}
}
cout << res << endl;
}
return 0;
}