1. 程式人生 > >codeforces - 723C 題解

codeforces - 723C 題解

div algo bool pre algorithm while clu style 問題

題目大意是:給定一個歌曲演唱的序列,第i個數字代表第i首歌由ai號樂隊演唱;問如何用最少的操作將這些歌改成1-m號樂隊演唱,且每個樂隊演唱歌曲數的最小值最大。

問題解法:首先分析如何讓最小值最大,有兩種方式來提升最小值,第一種是將1-m範圍外的樂隊演唱的歌分給1-m範圍內的演唱數最小的樂隊,第二種是將1-m內演唱數較大的樂隊的歌分一些給1-m內演唱數較小的樂隊。所以題目的貪心策略也就基本確定了

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<climits>
 4 using namespace
std; 5 int a[10001]; 6 int b[10001]={}; 7 int n,m; 8 int board; 9 bool check() 10 { 11 for(int i=1;i<=m;i++) 12 { 13 if(b[i]<board) 14 { 15 return true; 16 } 17 } 18 return false; 19 } 20 int main() 21 { 22 cin>>n>>m; 23 for
(int i=1;i<=n;i++) 24 { 25 cin>>a[i]; 26 if(a[i]<=m) 27 { 28 b[a[i]]+=1; 29 } 30 } 31 int res1,res2=0; 32 board=n/m; 33 for(int i=1;i<=n;i++) 34 { 35 if(a[i]>m) 36 { 37 for(int j=1;j<=m;j++)
38 { 39 if(b[j]<n/m) 40 { 41 b[j]+=1; 42 a[i]=j; 43 res2+=1; 44 break; 45 } 46 } 47 } 48 } 49 while(check()) 50 { 51 for(int i=1;i<=n;i++) 52 { 53 if(b[i]>board) 54 { 55 for(int j=1;j<=m;j++) 56 { 57 if(b[j]<board) 58 { 59 for(int k=1;k<=n;k++) 60 { 61 if(a[k]==i) 62 { 63 a[k]=j; 64 b[i]-=1; 65 b[j]+=1; 66 res2+=1; 67 break; 68 } 69 } 70 if(b[i]<=board) 71 { 72 break; 73 } 74 } 75 } 76 } 77 } 78 } 79 res1=INT_MAX; 80 for(int i=1;i<=m;i++) 81 { 82 res1=min(res1,b[i]); 83 } 84 cout<<res1<<" "<<res2<<endl; 85 for(int i=1;i<=n;i++) 86 { 87 cout<<a[i]<<" "; 88 } 89 return 0; 90 }

codeforces - 723C 題解