CF1065C Make It Equal
Posted bztminamoto
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1065C Make It Equal相关的知识,希望对你有一定的参考价值。
题意翻译
有一个长度为n的序列。
定义切割操作为把序列中所有大于等于H(自定义)的数变为H,定义其代价为操作前后序列中所有数的变化量的和。
定义一个“好的”切割操作为代价小于等于K的操作。
问至少需要多少次“好的”切割操作才可以使序列中的所有数的大小均相等。
本来以为高度都是$1e9$级别的……然后冥思苦想了一个很好的做法……结果发现高度只有$2e5$级别……那不就是个水题么……
还是说一下我的做法吧……
考虑一下,如果竖着分割,那么相当于是原来的数组,那么如果我们按高度横着分割,每一层都有一定数量的点,那么题目就相当于每一次从最上层开始取连续的几层,且每一次取得总点数不超过$K$
这个东西肯定是贪心的,能多取就多取,而且发现如果按这样分割的话每一层的点数不会超过$n$,且点数是递增的
那么我们可以开一个桶,$cnt[i]$表示点数为$i$的总共有多少层,那么同一组内我们可以直接算出不超过$k$的话一次最多取多少,设为$t=i/k$,那么$res+=cnt[i]/t$
然后我们这样是整除的,所以每一层还会有剩下的,又因为我们取得时候必须先取完点数小的再取点数大的,所以记一个$add$表示前面还留了多少贡献,然后在1计算上面每一层取多少次之前先判断一下$add$要取掉多少就行了
然后记得最后如果$add$还有值的话要$++res$
1 //minamoto 2 #include<bits/stdc++.h> 3 #define ll long long 4 using namespace std; 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 6 char buf[1<<21],*p1=buf,*p2=buf; 7 inline int read(){ 8 #define num ch-‘0‘ 9 char ch;bool flag=0;int res; 10 while(!isdigit(ch=getc())) 11 (ch==‘-‘)&&(flag=true); 12 for(res=num;isdigit(ch=getc());res=res*10+num); 13 (flag)&&(res=-res); 14 #undef num 15 return res; 16 } 17 const int N=2e5+5; 18 int cnt[N],a[N],n,res;ll add=0,k,p; 19 inline bool cmp(int a,int b){return a>b;} 20 int main(){ 21 n=read(),k=read(); 22 for(int i=1;i<=n;++i) a[i]=read(); 23 sort(a+1,a+1+n,cmp); 24 for(int i=1;i<n;++i) cnt[i]=a[i]-a[i+1]; 25 for(int i=1;i<n;++i){ 26 if(add+1ll*i*cnt[i]<=k) add+=1ll*i*cnt[i]; 27 else{ 28 p=(k-add)/i,cnt[i]-=p,++res,add=0; 29 p=k/i,res+=cnt[i]/p,cnt[i]%=p; 30 add=1ll*cnt[i]*i; 31 } 32 } 33 if(add) ++res; 34 cout<<res<<endl; 35 return 0; 36 }
以上是关于CF1065C Make It Equal的主要内容,如果未能解决你的问题,请参考以下文章
F - Make It Equal CodeForces - 1065C