日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces - 1328F Make k Equal(模拟)

發布時間:2024/4/11 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 1328F Make k Equal(模拟) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個數列 a ,現在有兩種操作:

  • 找到一個最小值,使其值加一
  • 找到一個最大值,使其值減一
  • 注意這里找到一個最值進行的操作,是針對最值不唯一的情況,題目問至少需要進行多少次操作,可以使得某個數字出現的次數大于等于 k 次

    題目分析:一道不知道為什么放在F題的F題。。因為E題卡了半個小時最后還沒解決掉,還剩十分鐘結束比賽的時候看到群友說F題是模擬,抓緊時間去讀題,讀完題后感覺還算蠻簡單的,稍微寫了寫調了一下,補題的時候交上去直接就A了,有種上當了的感覺

    因為兩種操作無非是從最小值往上一直加一,或者是從最大值一直往下減一,不難想到前綴和,所以這里我定義四個數組:

  • cnt[ i ]:從最小值開始到值為 i 的數為止(包括 i ),共有多少個數
  • inv_cnt[ i ]:從最大值開始到值為 i 的數為止(包括 i ),共有多少個數
  • sum[ i ]:將小于值為 i 的數都變成 i 所需要的操作數
  • inv_sum[ i ]:將大于值為 i 的數都變成 i 所需要的操作數
  • 這里單獨講一下 cnt 數組和 sum 數組的轉移方程,inv_cnt 和 inv_sum 大同小異,這里就不展開說了

    cnt 數組就是一個單純的前綴和:cnt[ i ] = cnt[ i - 1 ] + num[ i ] ,num數組是值為 i 的數出現了幾次

    sum 數組的轉移需要稍微想一下,需要借助 cnt 數組,不是很難:sum[ i ] = sum[ i -1 ] + cnt[ i -1 ] * 1 ,這里乘以 1 看似沒用,但是需要理解,這個 1 的實際意義是當前數字與前一個數字之差,即 ( i ) - ( i - 1 ) = 1

    到此為止,當我們處理好了 sum 數組和 cnt 數組之后,O( n )掃一遍維護答案就好了,具體維護方法可以分情況討論一下:對于當前的數 a:

  • 如果 num[ a ] >= k ,答案顯然為 0 ,直接退出循環輸出答案即可
  • 如果 cnt[ a ] >= k,意思為將小于數 a 的值全部變成 a 后,此時數 a 的出現次數大于等于 k 了
  • 如果 cnt[ a ] >= k,意思為將大于數 a 的值全部變為 a 后,次數數 a 的出現次數大于等于 k 了
  • 將所有的數都變為數 a?
  • 對于上面的四種情況,維護答案的最小值就好了

    有一點需要注意的是,這個題目的數據范圍給的很大,也就是說需要進行離散化處理,或者可以直接用map代替離散化,代價是每次操作都有logn的時間開銷,具體實現看代碼吧,就是上面的原理實現,別被復雜的stl碼風嚇到了

    代碼:
    ?

    #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=2e5+100;map<int,LL>mp,cnt,inv_cnt,sum,inv_sum;int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,k;scanf("%d%d",&n,&k);for(int i=1;i<=n;i++){int num;scanf("%d",&num);mp[num]++;}auto pre=mp.begin();auto it=pre;it++;cnt[pre->first]=pre->second;sum[pre->first]=0;while(it!=mp.end())//維護 cnt 和 sum{cnt[it->first]=cnt[pre->first]+it->second;sum[it->first]=sum[pre->first]+cnt[pre->first]*(it->first-pre->first);pre=it;it++;}auto inv_pre=mp.rbegin();auto inv_it=inv_pre;inv_it++;inv_cnt[inv_pre->first]=inv_pre->second;inv_sum[inv_pre->first]=0;while(inv_it!=mp.rend())//維護 inv_cnt 和 inv_sum{inv_cnt[inv_it->first]=inv_cnt[inv_pre->first]+inv_it->second;inv_sum[inv_it->first]=inv_sum[inv_pre->first]+inv_cnt[inv_pre->first]*(inv_pre->first-inv_it->first);inv_pre=inv_it;inv_it++;}LL ans=0x3f3f3f3f3f3f3f3f;for(auto it:mp)//維護答案,四種情況{int pos=it.first;if(mp[pos]>=k){ans=0;break;}if(cnt[pos]>=k)ans=min(ans,sum[pos]-(cnt[pos]-k));if(inv_cnt[pos]>=k)ans=min(ans,inv_sum[pos]-(inv_cnt[pos]-k));ans=min(ans,sum[pos]+inv_sum[pos]-(n-k));}printf("%lld\n",ans);return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的CodeForces - 1328F Make k Equal(模拟)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。