题目大意
给一个数字串,再给一个 M M M,求这个数字串中有哪些子串的和大于或等于且最接近 M M M
输入
每组包含一个测试用例,每个用例的第一行有两个数 N ≤ 1 0 5 N\leq10^5 N≤105(表示数字串中数字的个数)和 M ≤ 1 0 8 M\leq10^8 M≤108(题意中的 M M M),第二行是 N N N个数表示数字串
输出
对每个样例,以格式i-j
输出和最接近
M
M
M的子串,如有多个按照i
升序排列
样例输入
16 15
3 2 1 5 4 6 8 7 16 10 15 11 9 12 14 13
5 13
2 4 5 7 9
样例输出
1-5
4-6
7-8
11-11
2-4
4-5
解析
模拟一遍,但是搜索时使用二分搜索。
同样的做法又是喜闻乐见的python
会超时,c++就AC。。。
超时的python代码
# -*- coding: utf-8 -*-
# @Time : 2019/6/5 18:56
# @Author : ValarMorghulis
# @File : 1044.py
n, m = 0, 0
sum = list()
def search(i):
left, right = i, n
while left < right:
mid = (left + right) // 2
if sum[mid]-sum[i-1] >= m:
right = mid
else:
left = mid + 1
return right, sum[right] - sum[i - 1]
def solve():
global n, m, sum
n, m = map(int, input().split())
a = list(map(int, input().split()))
a = [0] + a
sum = [0 for i in range(n + 5)]
for i in range(1, n + 1):
sum[i] = a[i]
sum[i] += sum[i - 1]
ans = list()
minsum = sum[n]
for i in range(1, n + 1):
t, tmpsum = search(i)
if tmpsum > minsum:
continue
if tmpsum >= m:
if tmpsum < minsum:
ans.clear()
minsum = tmpsum
ans.append([i, t])
for i in range(0, len(ans)):
print("%d-%d" % (ans[i][0], ans[i][1]))
if __name__ == "__main__":
solve()
AC的c++代码
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<string>
#include<cmath>
#define inf 0xffffffff
using namespace std;
int n, m;
vector<int> sum, ans;
int b_search(int i, int &t)
{
int left=i;
int right=n;
while(left<right)
{
int mid=(left+right)/2;
if(sum[mid]-sum[i-1]>=m)
right=mid;
else
left=mid+1;
}
t=right;
return sum[t]-sum[i-1];
}
int main()
{
scanf("%d%d", &n, &m);
sum.resize(n+5);
for(int i=1; i<=n; i++)
{
scanf("%d", &sum[i]);
sum[i]+=sum[i-1];
}
int minsum=sum[n];
for(int i=1; i<=n; i++)
{
int t, tmpsum;
tmpsum=b_search(i, t);
if(tmpsum>minsum)
continue;
if(tmpsum>=m)
{
if(tmpsum<minsum)
{
minsum=tmpsum;
ans.clear();
}
ans.push_back(i);
ans.push_back(t);
}
}
for(int i=0; i<ans.size(); i+=2)
printf("%d-%d\n", ans[i], ans[i+1]);
return 0;
}