写在前面
- 思路分析
- 理解题意
For each test case, print i-j in a line for each pair of i ≤ j such that Di + ... + Dj = M. Note that if there are more than one solution, all the solutions must be printed in increasing order of i.
- 恰好等于
If there is no solution, output i-j for pairs of i ≤ j such that Di + ... + Dj >M with (Di + ... + Dj −M) minimized.
- 不能恰好等于,付出最少价格(总和必须⼤大于等于所给值)
- 简单模拟,2个超时。
- 后来sum数组递增,改用⼆分法查找
- 即sum[i]表示1~i的所有数字的总和~
- 理解题意
- 题目有难度,活灵活用ing
测试用例
-
input: 16 15 3 2 1 5 4 6 8 7 16 10 15 11 9 12 14 13 output: 1-5 4-6 7-8 11-11 input: 5 13 2 4 5 7 9 output: 2-4 4-5
ac代码
-
#include <vector> #include <iostream> using namespace std; vector<int> sum, result; int n, m; void binary_searchs(int i, int &j, int &tmpsum) { int left = i, right = n; while(left < right) { int mid = (left + right)/2; if(sum[mid] - sum[i-1] >= m) right = mid; else left = mid + 1; } j = right; tmpsum = sum[j] - sum[i-1]; } int main() { scanf("%d%d", &n, &m); sum.resize(n+1); for(int i=1; i<=n; i++) { scanf("%d", &sum[i]); sum[i] += sum[i-1]; } int minans = sum[n]; for(int i=1; i<=n; i++) { int j, tmpsum; binary_searchs(i, j, tmpsum); if(tmpsum > minans) continue; if(tmpsum >= m) { if(tmpsum < minans) { result.clear(); minans = tmpsum; } result.push_back(i); result.push_back(j); } } for(int i=0; i<result.size(); i+=2) printf("%d-%d\n", result[i], result[i+1]); return 0; }
学习代码
- 题意分析
- 给出1个数字序列与1个数S,在数字序列中求出所有和值为S的连续子序列(区间下标左端点小的先输出,左端点相同时右端点小的先输出)。
- 若没有这样的序列,求出和值恰好大于S的子序列(即在所有和值大于S的子序列中和值最接近S)
- 半懂状态,有时间多调试、可自行实现1把
#include<iostream> #include<algorithm> #define MAX 100001 using namespace std; int diamonds[MAX]; int main() { int N,M,input; while(cin>>N>>M) { int minlost = 99999999; int low = 0; bool notFound = true; fill(diamonds,diamonds+MAX,0); for(int i=1; i<=N; i++) { cin>>diamonds[i]; diamonds[i]+=diamonds[i-1]; while(diamonds[i] - diamonds[low]>M) { minlost = min(minlost,diamonds[i] - diamonds[low]); low++; } if(diamonds[i] - diamonds[low] == M) { cout<<low+1<<"-"<<i<<endl; notFound = false; } } if(notFound) { low = 0; for(int i=1; i<=N; i++) { while(diamonds[i] - diamonds[low]>minlost) low++; if(diamonds[i] - diamonds[low]==minlost) { cout<<low+1<<"-"<<i<<endl; } } } } return 0; }
知识点小结
lower_bound( begin,end,num)
lower_bound( begin,end,num,greater<type>() )
- 第1个大于等于num的数字,能发挥数字地址
- 不存在返回end
upper_bound( begin,end,num)
upper_bound( begin,end,num,greater<type>() )
- 第1个大于num的数字
- 不存在返回end
- 代码示例1
-
// lower_bound/upper_bound example #include <iostream> #include <algorithm> #include <vector> using namespace std; int main () { int myints[] = {10,20,30,30,20,10,10,20}; vector<int> v(myints,myints+8); // 10 20 30 30 20 10 10 20 vector<int>::iterator low,up; sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30 low=lower_bound (v.begin(), v.end(), 20); // ^ up= upper_bound (v.begin(), v.end(), 20); // ^ cout << "lower_bound at position " << int(low- v.begin()) << " " << myints[int(low- v.begin())+1] << endl; cout << "upper_bound at position " << int(up - v.begin()) << " " << myints[int(up- v.begin())+1] << endl; return 0; }