SWJTU第十六届 ACM“新秀杯”决赛-部分题目题解
C:人口普查
描述
2020年12月13日,人口普查员jyz前往太空普查行星K-452b上的人口。1小时后,jyz完成了他的人口普查任务。
经统计,行星K-452b上有n个人,每个人都有自己的出生年份和死亡年份。求哪一年该星球上的人口数量最多,最多时有多少人。
输入
第一行1个整数 n ( 1 <= n <= 10^5)
接下来n行,每行2个数b、d(1 <= b < d <= 10^9 ),分别表示这个人的出生日期和死亡日期。
输出
一行,2个整数,用空格隔开,分别为人口数量最多的年份y和第y年上的人口数量k。
当存在多个y符合题意时,输出最小的y和对应的k。
输入样例 1
4
4 6
3 4
4 5
8 10
输出样例 1
4 2
提示
每个人活了d-b年。在第4年,第二个人刚去世,不算进总人口。第1、3两个人活着。
思路:
首先对出生年份和死亡年份排序,遍历出生年份。当前出生年份小于死亡年份时人口数量+1,并同时判断当前的人口数是否为最大人口数;大于死亡年份时人口数量-1。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int b[100000+10],d[100000+10];
int main(){
int n,k=1,max_people=1;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&b[i],&d[i]);
}
int date=b[0];
sort(b,b+n);
sort(d,d+n);
int i=1,j=0;
while(i<n&&j<n){
if(b[i]<d[j]){
k++;
if(k>max_people){
max_people=k;
date=b[i];
}
i++;
}
else {
k--;
j++;
}
}
printf("%d %d",date,max_people);
return 0;
}
D:胖生快餐店
描述
胖生来没事决定开一家名为汉包王的快餐店,该餐厅提供n种食物,编号从1到n。
第i种食物的利润是a_i。(注意:利润可能是负的,因为它使用了昂贵的原料) 第一天,胖生为第i种食物准备了b_i个盘子。汉包王快餐店的独特之处在于订购食物的过程。 胖生本人将为每个访客选择食物给该访客。并且在选择食物的时候,胖生会遵循以下规则:
1、每个访客应至少获得一道菜。
2、每一位游客得到的食物必须是从第一种食物开始,连续地获得。对于每种食物每个顾客都只会得到一盘。
例如,游客可能会得到第一类食物1盘,第二种食物1盘,第三种食物1盘。再比如游客不能只得到第一类食物和第三类食物。胖生想知道汉包王快餐店最多可容纳多少访客? 而且他想知道当为最大访问数时可以赚取的最大利润。
输入
第一行一个整数T(1<=T<=10)表示一共有多少组测试
每个测试:
第一行一个整数n(1<=n<=10^5)表示食物的种类
第二行包含n个用空格分隔开的数字ai(-10^9 <= a_i <=10^9表示一盘第i种食物能获得的利润
第三行包含n个用空格分隔开的数字bi(1<=b_i<=10^5)表示第i种食物有多少盘。
输出
对于每组测试,输出一行为“Case #x: y z”,其中x表示是第几个测试,y表示最大容纳的顾客数量,z表示最大的利润。
输入样例 1
2
3
2 -1 3
3 2 1
4
3 -2 3 -1
4 2 1 2
输出样例 1
Case #1: 3 8
Case #2: 4 13
提示
你的int存不下哦
思路:b_1为最大顾客数量,之后的顾客数量递减。若利润为负数则推到下一盘菜算共同的最大利润。变量类型使用long long。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
long long a[100000+10],b[100000+10];
int main(){
long long t,n,x=1,y;
long long z;
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
}
for(int i=0;i<n;i++){
scanf("%lld",&b[i]);
if(i>0)b[i]=min(b[i-1],b[i]);
}
y=b[0];
z=a[0]*b[0];
for(int i=1;i<n;i++){
if(a[i]>=0){
z=z+a[i]*min(b[i],b[i-1]);
}
else if(i!=n-1){
a[i+1]=a[i+1]+a[i];
b[i+1]=min(b[i],b[i+1]);
}
}
printf("Case #%lld: %lld %lld\n",x++,y,z);
}
return 0;
}