游游的k-好数组 下标余数

思路

例如[1 2 2 1]数组,长度为3的数组为[1 2 2] 和 [2 2 1],有此例子可以知道,两个区间必有2个元素是一样的,要使所有长度为3的区间和相等,那么两个区间里面的元素必定要相同,即第i个元素的值要等于第i+k个元素的值,才是k-好数组。

先来引入什么是下标余数

当我们想要访问数组中的元素时,通常会使用下标来定位。在某些情况下,我们可能需要通过某种计算来确定一个元素的位置,这时就可以使用取余运算来确保得到的下标不会超出数组的界限。例如,如果有一个长度为10的数组,当我们尝试访问第13个元素时,可以使用13除以10的余数来确定该元素的下标,即13 % 10结果为3,这样就可以通过arr[3]来访问第13个元素而不会出现越界错误。

下标余数:0 1 2 0
数组:   1 2 2 1
每一组len = k 的元素下标:
        0 1 2
        1 2 0
可以知道余数相同的值要一样才能是好数组     
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int a[N];
int n,k,x;
vector<int> tr[N];  //用来存i%k的值,即i,i+k……等的值
void solve(){
    cin>>n>>k>>x;
    for(int i=0;i<k;i++) tr[i].clear();  //初始化
    for(int i=0;i<n;i++){
        cin>>a[i];
        tr[i%k].push_back(a[i]);  //每一组存的是a[i],a[i+k]……等等
    }
    int cnt=0;
    for(int i=0;i<k;i++){
        sort(tr[i].begin(),tr[i].end()); //排序
        for(int v:tr[i]){         //全部变成最大的那个值需要操作的次数
            cnt+=tr[i].back()-v;  //因为每次操作只能加,所以最终每组的数都会变成最大的那个数
        }
    }
    x-=cnt;    //总操作减去上面操作的次数
    if(x<0){   //小于0则无法变成好数组
        cout<<-1<<'\n';
        return ;
    }
    int ans=0;
    for(int i=0;i<k;i++){  //找剩余操作数操作完后的最大数
        ans=max(ans,tr[i].back());
        int len=tr[i].size();
        ans=max(ans,(int)tr[i].back()+x/len); //x/len是因为每个数都要同时加
    }
    cout<<ans<<'\n';
}
signed main(){
    int t;
    cin>>t;
    while(t--) solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值