贪心
P3627 最大差值
把n个数想象成n桶水,每次最多可以将一桶水全部倒入另外一桶,k次操作之后,最小值一定是0,每一次倒水相当于将两数合并,所以一共合并了(k+1)个数,因此答案就是最大的(k+1)个数的和
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=2e5+10;
int n;
int w[N];
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
sort(w+1,w+1+n);
LL res=0;
for(int i=n;i>=n-k;i--) res+=w[i];
printf("%lld\n",res);
}
return 0;
}
P3661 重置数列
贪心思想
切入点:a的范围是1~100,所以最后一定是把这n个数变成1 ~100的某一个数
第一步:枚举结果c,相当于最后把所有数变成c
第二部:计算至少需要操作多少次,具体思路如下:
从前往后找,找到第一个不是c的数,从这个点开始,长度为k的区间全部变成c,这样一定是最优解,统计一下要变多少次,最后在所有枚举的情况中选最小值
时间复杂度为O(100*n)=O(
1
0
7
10^7
107)
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,k;
int w[N];
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++) scanf("%d",&w[i]);
int res=n;//最坏情况要变n次
for(int i=1;i<=100;i++){//枚举结果
int cnt=0;
for(int j=0;j<n;j++){
if(w[j]!=i){
cnt++;
j+=k-1;//上面有个j++
}
}
res=min(res,cnt);
}
printf("%d\n",res);
}
return 0;
}