标签:
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 11284 | Accepted: 4694 |
Description
Input
Output
Sample Input
2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
Sample Output
2
3
Source
题目大意:
给定T组数据,每组数据有一个数n,表示有n个数,然后再给定一个数S,让你求这个数列总和>=S的长度的最小值。(数据范围 n<1e5,S<1e8,a[i]<=1e4)
解题思路:
(1)首先说一下复杂度为 O(n*log(n))的算法
因为所有的元素都是>0的,所以我们可以想到的是假设数列 ai ai+1 ai+2 ....at-1 的和>=S,那么我们可以求一下这些数列的前i项和,现在定义sum[i]为a0 a1 a2 ...ai-1的,那么ai ai+1 ai+2 ... at-1 就可以写成 sum[t] - sum[i], 因为 sum[t]-sum[i] >= t,那么我们要求的是这些长度的最小值,所以就是 t-i 的最小值,那么我们可以先预处理计算sum[i]的值,然后在可以进行二分算法求 t-i 的最小值
My Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100000+5;
int a[MAXN],sum[MAXN];
int n;
void get_Sum()
{
sum[0] = 0;
for(int i=0; i<n; i++)
sum[i+1] = sum[i] + a[i];
}
int main()
{
int T,S;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&S);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
get_Sum();
if(sum[n] < S)
puts("0");
else
{
int ans = n + 100;
for(int i=0; sum[i]+S<=sum[n]; i++)
{
int tmp = lower_bound(sum+i,sum+n,S+sum[i])-sum;
ans = min(ans,tmp-i);
}
cout<<ans<<endl;
}
}
return 0;
}
现在就得说一下尺取法了,其实尺取法的关键就是两个指针都是从头开始的,两个指针s, t,if(sum<S)那么sum+=a[t],t++;否则的话,sum -= a[s],s++;抓住这个关键就行了,在不满足条件的时候不要忘记更新 ans,ans始终是s-t的最小值。。。
My Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100000+5;
int a[MAXN];
int main()
{
int T,S,n;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&S);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
int t=0, s=0, sum=0;
int ans = n + 100;
while(1)
{
while(t<n && sum<S)
{
sum += a[t];
t++;
}
if(sum < S)
break;
ans = min(ans, t-s);
sum -= a[s];
s++;
}
if(ans == n+100)
puts("0");
else
{
cout<<ans<<endl;
}
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/qingshui23/article/details/51228072