经过昨天的折磨,今天写这个二分加前缀和真的得心应手,嘿嘿,小小得瑟一下。
我们首先用二分去枚举时间点,使用check去检查这个时间点是否能满足要求,即无论删除哪一个人始终在这个时间点下的贡献度之和都大于等于m,那么在这个时间点肯定是能达到五维世界的。
时间复杂度为O(NlogN)
#include<iostream>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1e5+5;
int n,m;
//t代表一共有多少个科学家有理解力
int t=0;
PII arr[N];
//判断此时的年份是否可以提供足够的时间供人类理解五维
//即使是在任何一个人被抹杀的情况下
bool check(LL u) {
//sum代表前缀和,sum[i]代表前i个人在u时间点内所贡献的理解力
LL sum[N];
for(int i=1; i<=t; i++) {
sum[i]=sum[i-1]+max(0ll,u-arr[i].first)*arr[i].second;
}
for(int i=1;i<=t;i++){
//如果去掉第i个人,总贡献度小于m,返回假
if(sum[t]-sum[i]+sum[i-1]<m)return false;
}
return true;
}
int main(void) {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) {
int a,b;
scanf("%d%d",&a,&b);
//如果一个人的理解速度是0,那么这个人对人类理解五维没有影响
//且小度也不会为一个没有理解力的人耗费魔法
if(b==0)continue;
arr[++t]= {a,b};
}
//如果有理解力的人少于一个人,那么小度就可以抹杀这个人
//那么就没有人类可以理解了
if(t<=1) {
printf("-1");
return 0;
}
//假设只有一个人,且这个人开始理解的时间是2e9,理解速度是最少的1
//而m为2e9,此时能达到最大的理解年份为4e9;
LL l=1,r=4e9;
while(l<r) {
LL mid=l+r>>1;
//如果能在mid时间理解,则验证是否有更短的时间也可以理解
if(check(mid)) {
r=mid;
} else {
l=mid+1;
}
}
printf("%lld",r);
return 0;
}
这段代码是一个解决特定问题的程序。它的目标是确定一个科学家群体能否在一定时间内理解五维概念,并找到理解五维所需的最短时间。代码中使用了二分查找算法来找到这个时间。
下面是对代码的逐行解析:
#include<iostream>
:包含C++标准输入输出库。using namespace std;
:使用std
命名空间,使得可以不必前缀std::
来调用标准库的函数和对象。typedef long long LL;
:将long long
类型重定义为LL
,便于阅读和理解。typedef pair<int,int> PII;
:将pair<int, int>
类型重定义为PII
,这是一个用于存储两个整数对的类型。const int N=1e5+5;
:定义一个常量N
,值为100005。int n,m;
:声明两个整数变量n
和m
。int t=0;
:声明一个整数变量t
并初始化为0,用于记录有理解力的科学家数量。PII arr[N];
:声明一个PII类型的数组arr
,大小为N
,用于存储科学家的信息(包括他们的出现时间和理解力)。bool check(LL u) { ... }
:定义一个函数check
,输入参数是一个长整型数u
,返回一个布尔值。这个函数用于检查在给定的时间u
内,是否有足够的理解力来理解五维。main(void) { ... }
:程序的主函数,从这里开始程序的执行。- 在主函数中,首先通过输入获取两个整数
n
和m
,分别代表科学家的数量和需要的理解力。 - 接下来,通过循环读取每个科学家的出现时间和理解力,并将它们存储在数组
arr
中。 - 如果有理解力的科学家数量少于或等于1,则输出"-1"并结束程序。
- 否则,使用二分查找算法在1到4e9之间查找最短的理解时间。如果能在某个时间
mid
内理解五维,则进一步查找更短的时间;如果不能,则查找更长的时间。 - 最后,输出找到的最短理解时间。
这个程序的核心是二分查找算法和check
函数的实现,它们共同决定了找到最短理解时间的效率