题目描述
给出一个数字N(1<=N<=100000),代表N个数字Ai(1<=Ai<=1000),这些数字从1开始编号。如果有某个区间的和为M(1<=M<=100000)输出这个区间的起始位置和结束位置,如果没有,输出-1;
输入格式
第一行两个正整数N(1<=N<=100000)和正整数M(1<=M<=100000)
第二行N个Ai(1<=N<=1000)
输出格式
区间的起始位置和终点位置
样例输入
20 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
样例输出
1 5
4 6
7 8
15 15
这道题很明显也应该使用双指针的思想。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
int n, m, t, now, l, r, c, b, T, k;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1.0);
int nx, ny, nz, ex, ey, ez;
ll mod = 1e9 + 7;
int sum[2022199];
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> sum[i];
sum[i] += sum[i - 1];//前缀和一下,方便记录两点中间的差值
}
bool check = 0;//判断是否输出-1
int r = 0, l = 0;//左指针和右指针都从原点出发
while (r <= n)//小于或者等于终点都行,判断的是是否等于该值
{
if (sum[r] - sum[l] < m)//小于的话就r++左指针向前
{
r++;
}
else if (sum[r] - sum[l] > m)//大于的话就右指针想前,范围收缩
{
l++;
}
else//输出
{
check = 1;
cout << l + 1 << " " << r<< endl;
r++;
}
}
if (!check)
{
cout << -1 << endl;
}
return;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//cin >> n;
//while (n--)
//{
solve();
//}
return 0;
}
优化版本
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
int n, m, t, now, l, r, c, T;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1.0);
int nx, ny, nz, ex, ey, ez;
ll mod = 1e9 + 7;
int e[2022199];
int maxx = 1e9 + 10;
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> e[i];
}
sort(e + 1, e + 1 + n);
int l = 1;
int ans = 0;
for (int i = 1; i <= n; i++)
{
if (e[i] - e[l] > m)
{
l++;
}
ans = max(ans, i - l + 1);//差分思想
}
cout << ans << endl;
return;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}