2022-03-27每日刷题打卡

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;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值