思路
参考算法笔记
- 枚举左端点,再找到第一个值为sum[i-1]+m的——这一步必须要用二分查找,不然会超时几个测试点
- 如果不存在,由于二分查找的结果是第一个大于等于m的值,因此结果比大于等于m,不等于m的话那么大于m,把这个值求出来
- 遍历一遍数组,一边遍历一边找符合条件的值
代码
#include<algorithm>#include<iostream>#include<vector>using namespace std;const int N = 100010;vector<int> sum(N);int n, m,nearM = 1000000000;int upper_bound(int L, int R, int x){int left = L, right = R, mid;while(left < right){mid = left + (right - left)/2;if(sum[mid]<=x) left = mid+1;else right = mid;}return left;}int main(){scanf("%d%d",&n,&m);sum[0] = 0;for(int i = 1; i <= n; i++){scanf("%d",&sum[i]);sum[i] += sum[i-1];}for(int i = 1; i <= n; i++){int j = upper_bound(i, n + 1, sum[i-1] + m);if(sum[j-1] - sum[i-1]==m){//这里j要-1nearM = m;break;} else if(j <= n&&sum[j] - sum[i - 1] < nearM){//这个一定是大于m的nearM = sum[j] - sum[i - 1];}}for(int i = 1; i <= n; i++){int j = upper_bound(i, n + 1, sum[i - 1] + nearM);if(sum[j - 1] - sum[i - 1] == nearM){printf("%d-%d\n",i,j-1);}}return 0;}
自己写的复杂度是O(n^2)级的,有三个测试点超时了
#include<algorithm>#include<iostream>#include<vector>using namespace std;int main(){int n, m;scanf("%d%d", &n, &m);vector<int> input(n+1),sum(n+1);vector<int> left, right;sum[0] = 0, input[0] = 0;for(int i = 1; i <= n; i++){scanf("%d", &input[i]);sum[i] = sum[i-1] + input[i];}for(int i = 1; i<= n; i++){for(int j = i; j <= n; j++){if(sum[j]-sum[i-1]==m){//第i个到第j个的和left.push_back(i);right.push_back(j);}}}int len = left.size();if(len == 0){//没有数字加入,找第一个大于m的和int temp = m;m = 1000000000;for(int i = 1; i<= n; i++){for(int j = i; j <= n; j++){if(sum[j]-sum[i-1]<m&&sum[j]-sum[i-1]>temp){//第i个到第j个的和m = sum[j]-sum[i-1];break;}}}//再找一次for(int i = 1; i<= n; i++){for(int j = i; j <= n; j++){if(sum[j]-sum[i-1]==m){//第i个到第j个的和left.push_back(i);right.push_back(j);}}}}len = left.size();for(int i = 0; i < len; i++){printf("%d-%d\n",left[i],right[i]);}}
