Codeforces Round #490 (Div. 3) D. Equalize the Remainders(好奇怪的迭代器用法)

原题地址:http://codeforces.com/contest/999/problem/D
题意:本题就是给你n,m,保证n能被m整除,给你n个数,对这些数操作+=1,使得这些数%m后,得到的数是从0~m-1,且没个数出现n/m次。

思路:贪心,首先记录每个取余m后的结果数的个数,如果个数不大于n/m则不用改变,否则(需要改变)插入set,然后二分查找出大于该数的且余数个数小于n/m的数,把数组变化,同时更新对应值。注意如果找不到大于该数的且余数个数小于n/m的数,就是小于它的第一个数。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const  int maxn = 3e5 + 5;
ll a[maxn];
ll dir[maxn];
ll n, m;
int main() {
    scanf("%I64d%I64d", &n, &m);
    ll num = n / m;
    for(ll i = 1; i <= n; i++) {
        scanf("%I64d", &a[i]);
        dir[a[i] % m]++;
    }

    set<ll>s;

    for(ll i = 0; i < m; i++) {
        if(dir[i] < num) s.insert(i);
    }
    ll ans = 0;
    for(ll i = 1; i <= n; i++) {
        if(s.size() == 0) break;
        if(dir[a[i] % m] <= num) continue;
         dir[a[i] % m]--;
         set<ll>::iterator it;
       it = s.lower_bound(a[i] % m);
//it=lower_bound(s.begin(),s.end(),a[i]%m);
//这里特别奇怪,如果用下面这种写法的话,就会T
        if(it != s.end()) {
            dir[*it]++;
            ans += *it - a[i] % m;
            a[i] += *it - a[i] % m;
            if(dir[*it] == num) s.erase(*it);
        } else {
            dir[*s.begin()]++;
            ll k = m  - a[i] % m;
            k += *s.begin();
            ans += k;
            a[i] +=k;
            if(dir[*s.begin()] == num) s.erase(*s.begin());
        }
    }
    printf("%I64d\n", ans);
    for(int i = 1; i <= n; i++) printf("%I64d ", a[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/80979097