这是一个炎热的夏日。
懒洋洋的奶牛贝茜想将自己放置在田野中的某个位置,以便可以在短距离内尽可能多地吃到美味的草。
贝茜所在的田野中共有 NN 片草地,我们可以将田野视作一个一维数轴。
第 ii 片草地中包含 gigi 单位的青草,位置坐标为 xixi。
不同草地的位置不同。
贝茜想选取田野中的某个点作为她的初始位置(可能是某片草地所在的点)。
只有一片草地与她的初始位置的距离不超过 KK 时,贝茜才能吃到那片草地上的草。
如果贝茜选择最佳初始位置,请确定她可以吃到的青草最大数量。
输入格式
第一行包含两个整数 NN 和 KK。
接下来 NN 行,每行描述一片草地,包含两个整数 gigi 和 xixi。
输出格式
输出如果贝茜选择最佳初始位置,则她可以吃到的青草最大数量。
数据范围
1≤N≤1051≤N≤105,
1≤gi≤100001≤gi≤10000,
0≤xi≤1060≤xi≤106,
1≤K≤2×1061≤K≤2×106
输入样例:
4 3
4 7
10 15
2 2
5 1
输出样例:
11
样例解释
最佳初始位置选择为 x=4x=4,可以吃到 x=1,x=2,x=7x=1,x=2,x=7 处的青草。
解析:数据范围为1e6,普通n^2遍历会超时,可以选前缀和,每次查询进行o(1)操纵降复杂度
(双指针算法分析:双指针需要保证每次都是单调的,i向后移动,j也要向后移动,本题i可以表示最右边界,j表示最左边界,一定单调所以可以)
代码记录:
#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int,int > pll;
const int N = 1e5+5;
int n,k;
pll q[N];
int main()
{
scanf("%d%d",&n,&k);
for(int i = 1;i <= n;i ++)
{
scanf("%d%d",&q[i].y,&q[i].x); //将x坐标存在first里,方便进行排序
}
sort(q+1,q+n+1);
int res=0,sum=0;
for(int i=1,j=1;i<=n;i++)
{
sum+=q[i].y;
while(q[i].x-q[j].x>k*2)sum-=q[j++].y;
res=max(res,sum ); //如滑动窗口一样每次进行更新
}
cout<<res<<endl;
return 0;
}
差分分析:双指针是对于草来说的,差分就是对于牛来说,分析每一堆草对左右k范围牛位置的贡献值,然后找最大就行
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N =3e6+5;
int n,k;
int b[N]; //差分数组
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
int x,g;
cin>>g>>x;
if(x-k<0)
b[0]+=g;
else if(x-k>=0)
b[x-k]+=g;
b[x+k+1]-=g;
}
int sum=0,res=0;
for(int i=0;i<=N;i++)
{
sum+=b[i];
res=max(res,sum);
}
cout<<res<<endl;
return 0;
}