Codeforces Round #540 (Div. 3)(部分题解)

版权声明:本文章未经博主允许不得转载 https://blog.csdn.net/qq_42217376/article/details/87905072

链接:http://codeforces.com/contest/1118
来源:Codeforces



A. Water Buying

在这里插入图片描述

  题意:用最小的花费买到刚好合适的东西.我们可以求出两种方案的花费,最后输出最小的即可.

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#define pi 3.1415926
#define mod 1000000007
#include<algorithm>
using namespace std;

typedef long long LL;
const int Max_n=100005;
LL a[Max_n];

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		LL n,a,b;
		scanf("%lld%lld%lld",&n,&a,&b);
		LL res,res1;
		if(n&1)	res=a+(n-1)/2*b;
		else res=n/2*b;
		res1=n*a;
		printf("%lld\n",res>res1?res1:res);
	} 
	return 0;
}

B. Tanya and Candies(前缀和)

在这里插入图片描述
  题意:给你一个数组,删除其中一个元素,剩下的元素奇数位和偶数位的元素和相等,问这样的元素有多少个.我们可以用两个数组分别维护奇数位和偶数位的前缀和,当我们将某一个元素删除时,前面的不变,后面的位置奇偶互换.此时奇数和就是:sum1[i-1]+sum2[n]-sum[i](sum保存的分别是奇数和与偶数和),偶数和就是:sum2[i-1]+sum1[n]-sum1[n]-sum1[i]

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long LL;
const int Max_n=200005;
int sum1[Max_n],sum2[Max_n],a[Max_n];

int main() {
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        if(i&1){
            sum1[i]=sum1[i-1]+a[i];//奇数和
            sum2[i]=sum2[i-1];//偶数和
        }else{
            sum1[i]=sum1[i-1];
            sum2[i]=sum2[i-1]+a[i];
        }
    }
    int ans=0;
    for(int i=1;i<=n;++i){
        int sumj,sumo;
        sumo=sum2[i-1]+sum1[n]-sum1[i];
        sumj=sum1[i-1]+sum2[n]-sum2[i];
        if(sumj==sumo) ans++;
    }
    printf("%d\n",ans);
    return 0;
}

D1. Coffee and Coursework (Easy version)(贪心)

在这里插入图片描述

C. Magic Ship(二分天数):https://blog.csdn.net/qq_42217376/article/details/87895706
  题意:有一个作业需要写m页,你有很多杯咖啡(一组数据),数值就代表喝一杯咖啡能够写多少页作业,在某一天你可以选择喝任意杯咖啡,但是当天的第一杯咖啡的贡献值是max(0,a1),第二杯就变成了max(0,a2-1),第三杯是max(0,a3-2),贡献值依次类推,让我们求最少多少天可以完成这些作业.上次写船那道题有一个奇特的想法那就是二分天数来找到最优解.这里我们可以枚举天数来找到最优解.(二分方法见下题.)

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long LL;
const int Max_n=200005;
int a[Max_n];

int main() {
    int n,m,sum=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        sum+=a[i];
    }
    if(sum<m){
        printf("-1\n");
        return 0;
    }
    sort(a+1,a+n+1,greater<int>());
    for(int days=1;days<=n;++days){//枚举天数
        int ans=0,cnt=0,b=0;
        for(int i=1;i<=n;i++){
            ans+=(a[i]-cnt);
            //假设我们当前有两天,我们把数组分成2组(贪心的规则去分组),计算出每组的和,最后找到最合适的天数.
            if(i%days==0) cnt++;
            if(ans>=m){
                b=1;
                break;
            }
        }
        if(b){
            printf("%d\n",days);
            break;
        }
    }
    return 0;
}

D2. Coffee and Coursework (Hard Version)(二分)

在这里插入图片描述

  题意同上题相同,只不过这里数据范围变了,我们没办法在使用枚举来求解这道题,此时就用到二分天数来求解.

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long LL;
const int Max_n=200005;
int a[Max_n],m,n;

bool check(int mid){
    LL sum=0;
    for(int i=0,days=0;i<n;i++){
        sum+=max(0,a[i]-days);
        if((i+1)%mid==0) days++;
    }
    return sum>=m;
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i)
        scanf("%d",&a[i]);
    sort(a,a+n,greater<int>());
    int l=1,r=Max_n,days=0;
    while(l<=r){
        int mid=l+((r-l)>>1);
        if(check(mid)){
            r=mid-1;
            days=mid;
        }else l=mid+1;
    }
    printf("%d\n",days?days:-1);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42217376/article/details/87905072