题目描述
给定一个长为n的数组,保证
>=0 。
接下来q次询问,每次询问给定,请你输出最小的r,满足1<=r<=n且
…
。如果不存在这样的r,请输出-1。
输入格式
第一行两个由空格分隔的整数表示n和q
第二行n个整数表示数组
接下来q行,每行一个整数表示一次询问。
输出格式
输出q行,对于第i行,如果有答案,请输出最小的满足要求的r;如果没有答案,请输出-1。
输入输出样例
样例输入 #1
3 7
1 2 3
0
1
2
3
4
5
6
样例输出 #1
1
1
2
2
3
3
3
-1
题目分析
数列求和后为……,满足有最小的r使得
>=每次规定的值即可
对于我们使用vector函数创建,防止内存不够
核心算法为二分查找法
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,q,m;
long long t;
cin >> n>>q;
vector<int> v(n + 1);
vector<long long> a(n + 1, 0);
for (int i = 1; i <= n; i++)
{
cin >> v[i];
a[i] = v[i]+a[i-1];
}
for(int i=1;i<=q;i++)
{
int l = 1, r = n ;
m = (l + r) / 2;
cin >> t;
while (1)
{
if (a[m] >= t&&a[m-1]<t||m==1)//如果a[m]>=t且前一个数a[m-1]<t,说明此时m是满足条件的最小值,直接输出并退出;其中有m==1的情况单独考虑(如果a[1]=0)
{
cout << m << endl;
break;
}
if (a[m] < t)//二分法,不会自己找
{
l = m + 1;
m = (l + r) / 2;
}
else
{
r = m;
m = (l + r) / 2;
}
if (l >r )//如果最终没找到,输出-1然后break就行
{
cout << "-1" << endl;
break;
}
}
}
return 0;
}
-------------------------------------------------------分割线-----------------------------------------------------------------
发现上边写的二分法复杂了,就想着简化一下,顺便把for循环改成while循环了
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,q,m;
long long sum;
cin >> n>>q;
vector<int> v(n + 1);
vector<long long> a(n + 1, 0);
for (int i = 1; i <= n; i++)
{
cin >> v[i];
a[i] = v[i]+a[i-1];
}
while(q--)//因为用不到i,所以可以吧for循环改为while,q个循环
{
int l = 1, r = n;
cin >> sum;
while (l < r)//二分法简化
{
m = (l + r) / 2;
if (a[m] >= sum) r = m;
else l = m + 1;
m = (l + r) / 2;
}
if (a[m] >= sum) cout << m << endl;//最终结果肯定l=r,此时若a[m]>=sum,输出sum,反之输出-1;
else cout << "-1" << endl;
}
return 0;
}