码迷,mamicode.com
首页 > 其他好文 > 详细

LA 2678 Subsequence(二分查找)

时间:2014-09-06 17:20:23      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   ar   for   art   

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=679

解题报告:给定一个正整数的序列,和一个S,求长度最短的子序列,使它们的和大于或等于S。序列长度n <= 100000

很明显,如果枚举起点和终点的话,时间复杂度是O(n^3),不行。怎么能在O(1)时间求出一个子序列的和是多少呢,可以用另一个数组sum[i],意义是第一个到

第i个数的和是sum[i],这样的话就可以做到在O(1)时间求出一个子序列的和,但这样还是不够,我的做法是只枚举子序列的终点,然后找到一个j使得sum[j] >= sum[i] - S,那么这个子序列的长度就是i - j + 1,因为sum[i]是递增的,在查找j的位置的时候用二分查找,所以,这样就把时间复杂度降到了n*log2(n),就可以过了。

bubuko.com,布布扣
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn = 100005;
 7 int A[maxn],sum[maxn];
 8 
 9 int find(int *B,int l,int r,int d)
10 {
11     while(l < r)
12     {
13         int mid = (l + r) >> 1;
14         if(d <= B[mid]) r = mid;
15         else l = mid + 1;
16     }
17     return l;
18 }
19 
20 int main()
21 {
22     int n,s;
23     while(scanf("%d%d",&n,&s)!=EOF)
24     {
25         int k = 0;
26         sum[0] = 0;
27         for(int i = 1;i <= n;++i)
28         {
29             scanf("%d",&A[i]);
30             sum[i] = sum[i-1] + A[i];
31             if(k == 0 && sum[i] >= s) k = i;
32         }
33         int ans = 0x7fffffff;
34         for(int i = k;i <= n;++i)
35         {
36             int t = find(sum,1,i,sum[i] - s);
37             if(sum[t] > sum[i]-s) t--;
38              ans = min(ans,i - t);
39         }
40         printf(ans > 100000? "0\n":"%d\n",ans);
41     }
42     return 0;
43 }
View Code

 

LA 2678 Subsequence(二分查找)

标签:style   blog   http   color   os   io   ar   for   art   

原文地址:http://www.cnblogs.com/xiaxiaosheng/p/3959554.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!