题解 | #游游的k好数组#

游游的数字圈

https://ac.nowcoder.com/acm/contest/62622/A

%k分类

假设k=3,第1个长度为k的区间和为s1=a1+a2+a3s_1=a_1+a_2+a_3(数组下标从1开始),第二个长度为k的区间和为s2=a2+a3+a4s_2=a_2+a_3+a_4

题目要求所有长度为k的区间和相等,也就是s1=s2s_1=s_2,因此a1=a4a_1=a_4,逐步迭代下去,由于每个区间和都相等,我们应该有:

a1=a4=a7=...=a3m+1m=0,1,2,...a_1=a_4=a_7 =... =a_{3m+1} \\ m = 0, 1, 2, ...

因此可以对数组按照%k进行分类,%k相同的做为一组,并且要保证这个组内的所有数都相。

对于某个组pp,由于每次的操作是+1,数字只能增加不能减少,所以需要找到组内的最大值mxmx,并将组内所有的数变成mxmx,所需要的时间是t=mx×p.size()sum(p)t=mx\times p.size() - sum(p).

计算出所有组所需要的时间cntcnt,如果cnt>xcnt > x,就输出-1

找到最大值

否则x -= cnt,为了拿到最大值,并且要保证每个组内的数都相等,可以遍历每个组,并将x均分给组内的每一个数,找到最后的最大值即可。


#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int a[N];

int n, k, x;

void solve(){
    cin >> n >> k >> x;
    for(int i = 1; i <= n; ++ i)
        cin >> a[i];
    unordered_map<int, vector<int> > mhash; // 存储i % k相同的数
    for(int i = 1; i <= n; ++ i)
        mhash[i % k].push_back(a[i]);
    int cnt = 0;
    for(auto& [k, v] : mhash){
        sort(v.begin(), v.end()); // 排序便于找最大值
        int mx = v.back(); // 最大值
        for(int& num : v){
            cnt += abs(num - mx); // num变为mx所需要的最大值
            num = mx; // 将num变为mx
        }
    }
    if(cnt > x) {cout << -1 << endl; return;}
    x -= cnt;
    int res = *max_element(a + 1, a + 1 + n); // 找到原来数组内的最大值
    for(auto& [k, v] : mhash){
        res = max(res, v.back() + x / (int)v.size());
    }
    cout << res << endl;
}

int main(){
    int T;
    cin >> T;
    while(T -- ){
        solve();
    }
}
全部评论
假设分给1组a次 分给2组b次 在取max对答案的贡献值的时候 如果把a+b都分给a或者分给b取max是一样的
点赞 回复 分享
发布于 2023-08-13 16:58 山东
为什么每次每次把 x 均分到每个组,最后的答案就是最优的?难道不能分一些给一个组,然后再分一些给另一个组吗?不是很理解这种思路。
点赞 回复 分享
发布于 2023-08-07 17:42 湖南

相关推荐

重生我想学测开:嵌入式的问题,我准备入行京东外卖了
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
06-18 16:15
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务