每日一题总结记录之1922. 懒惰的牛(主学双指针、次学差分、前缀和)

这是一个炎热的夏日。

懒洋洋的奶牛贝茜想将自己放置在田野中的某个位置,以便可以在短距离内尽可能多地吃到美味的草。

贝茜所在的田野中共有 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Monster_six

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值