【题意】
二分法版本:
找到和不小于一个给定值、但尽可能小的所有子串
【思路】
两个指针,分别指向子串头尾,具体看代码(有优化,比如说找到一个满足要求的子串后,下一次扫描左指针右移一位,右指针的起始位置就保持在上一次右指针的位置即可)。
【注意】
一开始有个case我一直超时,感觉也优化过了想不出来哪里有问题,于是跑去看看别人的思路,看见有二分法找右指针下标的,觉得可能是这个原因于是跑去码了二分的版本,依然超时orz。。。百思不得其解于是又跑去看了看别人的做法,这次发现关键问题了。。。就是 cin 和 cout 比 scanf 和 printf 费时,改了以后两种方法都过了。。。被这种问题坑过不止一次了,还是没长记性= =,再吸取一次教训好了
非二分法版本:
#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
using namespace std;
#define MAXIMUM 0x0fffffff
int main(int argc, char const *argv[])
{
map<int,int> pairs;
vector<int> input;
int n,m,min;
scanf("%d%d", &n, &m);
input.assign(n,0);
for(int i=0; i<n; i++){
scanf("%d", &input[i]);
}
min = MAXIMUM;
int subSum,start,end;
subSum = start = end = 0;
while(start<input.size()){
while(end<input.size() && subSum<m){
subSum += input[end];
end++;
}
if(subSum<m){
break;
}
else if(subSum<min){
pairs.clear();
pairs[start] = end-1;
min = subSum;
}
else if(subSum==min){
pairs[start] = end-1;
}
subSum -= input[start];
start++;
}
for(map<int,int>::iterator it=pairs.begin(); it!=pairs.end(); it++){
printf("%d-%d\n", (*it).first+1, (*it).second+1);
}
system("pause");
return 0;
}
二分法版本:
#include <iostream>
#include <map>
#include <vector>
#include <cstdio>
using namespace std;
#define MAXIMUM 0x0fffffff
int main(int argc, char const *argv[])
{
map<int,int> pairs;
vector<int> subSum;
int n,m,min;
scanf("%d%d", &n, &m);
subSum.assign(n+1,0);
for(int i=1; i<=n; i++){
scanf("%d",&subSum[i]);
subSum[i] += subSum[i-1];
}
min = MAXIMUM;
for(int i=0; i<n; i++){
int left,right,mid;
left = i+1;
right = n;
while(left<right){
mid = (left+right)/2;
if(subSum[mid]-subSum[i]<m){
left = mid+1;
}
else{
right = mid;
}
}
if(subSum[left]-subSum[i]<m){
break;
}
else if(subSum[left]-subSum[i]<min){
pairs.clear();
pairs[i+1] = left;
min = subSum[left]-subSum[i];
}
else if(subSum[left]-subSum[i]==min){
pairs[i+1] = left;
}
}
for(map<int,int>::iterator it=pairs.begin(); it!=pairs.end(); it++){
printf("%d-%d\n", (*it).first, (*it).second);
}
system("pause");
return 0;
}