题目大意 给定一个数组区间,给定数据和覆盖区间,求非覆盖区间;
由于题目给定的数据过大,无法直接用两重循环来进行遍历,因此对给定的数据进行预处理;
首先
for(int p=1;p<i;p++){
b[p]=a[p+1]-a[p];
}//差分数组;
其次,将差分数组排序后,挑选比所需要睡着时间长的数据,把后面的数据加合再减去n(符合的数据个数)*所需睡着时间长;再与预计睡觉总时长相比较;
但是我们会发现有两个难点:
一,如何寻找到所需数据;
二,如何将所需数据加合;
针对第一点我们不难发现使用复杂度为(n2)的必然超时,所以选择二分,降低时间复杂度
for(int k=1;k<=n;k++){
long long j,l;
scanf("%lld%lld",&j,&l);
int num=lower_bound(b+1,b+i,j)-b;//使用lower_bound输出的是地址,所以减去起始位置,得到你所需要的下标;
if(num>=i){
printf("No\n");
}
else{
if(c[i-1]-c[num-1]-j*(i-num)>=l)
printf("Yes\n");
else
printf("No\n");
}
}
对于数据加合的话,选择使用前缀和,把差分数组导入新的数组进行前缀和
for(int p=1;p<i;p++){
k=k+b[p];
c[p]=k;
最后
ac代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+1;
long long a[N],b[N],c[N];
int main(){
long long i,n,k=0;
long long sum=0;
scanf("%lld%lld",&i,&n);
for(int p=1;p<=i;p++){
scanf("%lld",&a[p]);
}
for(int p=1;p<i;p++){
b[p]=a[p+1]-a[p];
//printf("%d ",b[p]);
}
sort(b,b+i);
for(int p=1;p<i;p++){
k=k+b[p];
c[p]=k;
//printf("%d ",b[p]);
}
for(int k=1;k<=n;k++){
long long j,l;
scanf("%lld%lld",&j,&l);
int num=lower_bound(b+1,b+i,j)-b;
if(num>=i){
printf("No\n");
}
else{
if(c[i-1]-c[num-1]-j*(i-num)>=l)
printf("Yes\n");
else
printf("No\n");
}
}
}