题目描述
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
已知有n个动物朋友排成一排,每个动物朋友都有一个正整数的快乐值,涛涛每次会和连续的动物朋友玩,并且获得这些动物朋友快乐值的和的快乐,而涛涛是个完美主义者,他觉得快乐值刚好是m时候才是快乐的,现在请问有多少种选择方式,使得所选的连续的动物朋友的快乐值刚好为m。
输入描述
输出描述
示例1
输入:
11 45
1 4 1 9 19 8 10 8 1 2 3
输出:
1
思路1(双指针)
题意告诉我们要连续的区间,看示例1,连续的区间为 19,8 ,10,8
由此我们可以有一个思路就是,连续区间的起点从i(1<=i<=n)开始,依次相加,直到sum==m ,如果sum>m,则将起点往后挪一个,下面是代码。(首先左边界是从最左边开始的,随着右边界的变化,sum也在变化,当sum超过了m,左边界则也变化,有一种双指针的感觉)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int a[N];
signed main(){
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>a[i];
int sum=0;
int res=0;
for(int i=0,j=0;i<n;i++)
{
sum+=a[i];
while(sum>m) sum-=a[j++];
res += sum == m;
}
cout<<res;
return 0;
}
下面这个代码是双指针,和下面的前缀和思路一样
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int a[N];
signed main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]+=a[i-1];
}
int res=0;
int r=1;
for(int i=1;i<=n;i++)
{
while(r<n&&a[r+1]-a[i-1]<=m) r++;
if(a[r]-a[i-1]==m) res++;
}
cout<<res;
return 0;
}
思路2(二分+前缀和)
首先固定左边界,再想办法固定右边界,右边界越靠右越大,这时可以考虑用前缀和+二分来确定右边界。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int a[N];
signed main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]+=a[i-1];
}
int res=0;
for(int i=1;i<=n;i++)
{
int l=i,r=n;
while(l<r)
{
int mid=(l+r)/2;
if(a[mid]-a[i-1]>=m) r=mid;
else l=mid+1;
}
if(a[l]-a[i-1]==m) res++; //l是找到的右边界坐标
}
cout<<res;
return 0;
}
拓展
这一题和我之前做的一题的思路是一样的,链接如下:
(12条消息) 【Codeforces Round #799 (Div. 4)】E. Binary Deque_codeforces binary deque_咲月未羽的博客-CSDN博客
算法小白一枚,欢迎大家的交流和指正 。