1.题意
给出一个数n,然后达能连续数的和与n相等时,输出此区间;从题意不难看出,首先要使用的一个算法是前缀和,然后要找数的话,是双层循环,会超时,因此又用到一个基础算法,双指针。
2.思路
(1)输入数n;
(2)利用循环和前缀和,我简单优化了一下,根据简单数学知识得,n/2以后的两数相加一定大于n,因此循环到n/2,并且相加我怕数据会爆,因此用到了long long。
//前缀和:前缀和相对来说没有差分那么难,差分在博客海底高铁也有涉及;
//前缀和的话,主要就是利用另一个数组,将对应的前i项求出
# include <iostream>
using namespace std;
int a[100100],b[100100];
int main ()
{
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
//模板
for(int i=1;i<=n;i++) b[i]=b[i-1]+a[i];
while(m--)
{
int l,r;scanf("%d%d",&l,&r);
cout<<b[r]-b[l-1]<<endl;
}
return 0;
}
(3)本题计算出前缀和之后,就是求哪个区间是满足要求的,这时我们又需要用到双指针算法,双指针相对来说没有什么模板,但是他的主要功能就是优化代码,减少速度。
//本题利用双指针的代码
for(int i=1,j=1;i<=n&&j<=n;i++)
{
while(a[j]-a[i-1]<n) j++;
if(a[j]-a[i-1]==n) cout<<i<<" "<<j<<endl;
}
//本题不利于双指针的代码
for(int i=2;i<=n;i++)
{
for(int j=1;j<i;j++)
{
if((a[i]+a[j])==n)
cout<<i<<" "<<j<<endl;
}
}
//两者可以很容易的看出,利用双指针后时间是O(n);没有利用双指针前是O(n的平方)
3.源码
/*代码还是非常简短的;
但要熟练掌握两个算法才可。*/
# include <iostream>
using namespace std;
int main ()
{
int a[20000001];
int n;cin>>n;
//前缀和
for(int i=1;i<n;i++) a[i]=a[i-1]+i;
//双指针
for(int i=1,j=1;i<=n&&j<=n;i++)
{
while(a[j]-a[i-1]<n) j++;
if(a[j]-a[i-1]==n) cout<<i<<" "<<j<<endl;
}
return 0;
}