Codeforces 999D Equalize the Remainders (set使用)


題目連接:Equalize the Remainders

題意:n個數字,對m取余有m種情況,使得每種情況的個數都為n/m個(保證n%m=0),最少需要操作多少次? 每次操作可以把某個數字+1。輸出最少操作次數,和操作后的序列(可以輸出任意一種)。

題解:用一個set來維護所有余數x(當前余數為x的數個數沒湊夠n/m個),對於每個數假設這個數的余數為t,當余數為t的數個數沒湊夠n/m時那這個數就不需要改變,如果已經湊夠了,那就在set中找到第一個大於等於t的數(注意這里t可能比set中最大數的還要大,遇到這種情況就要將t變成set中最小數,舉個例子m=5,余數為4和為0的數字湊夠了,此時又來一個余數為4的數,該數應該變為余數為1)維護答案和序列,ans += (x-t+m)%m,out[i] += (x-t+m)%m。

 
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef pair<int,int> P;
 4 typedef long long LL;
 5 const int MAX_N =2e5+9;
 6 int N,M,T,S;
 7 LL vec[MAX_N];
 8 LL res[MAX_N]; // 當前模的個數
 9 set<int> s;
10 LL out[MAX_N];
11 int main()
12 {
13     while(cin>>N>>M){
14         memset(res,0,sizeof(res));
15         memset(out,0,sizeof(out));
16         s.clear();
17         for(int i=0;i<M;i++){
18             s.insert(i);
19         }
20         for(int i=0;i<N;i++){
21             scanf("%lld",&vec[i]);
22         }
23         LL ans =0 ;
24         for(int i=0;i<N;i++){
25             LL t = vec[i]%M;
26             LL x ;
27             if(t > *s.rbegin()) x = *s.begin();
28             else x = *s.lower_bound(t);
29             res[x] ++;
30             if(res[x] == N/M) s.erase(x);
31             ans += (x - t + M)%M;
32             out[i] = (x - t + M)%M;
33         }
34         cout<<ans<<endl;
35         for(int i=0;i<N;i++){
36             printf("%lld ",vec[i] + out[i]);
37         }
38         cout<<endl;
39     }
40     return 0;
41 }

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com