E

题目链接

 

题意:给出n个数,求加和大于x的最短区间的区间长度。

如果前i个数字和为y,那么如果前j数字的和小于等于y-x,那么i-j就是一种可能的情况,我们对于所有的i找出前面最大的j就可以了,因为数据量比较大,用树状数组来处理前n项的最大值,但是每个数字又可能比较大,所以先离散化处理一下。

AC代码

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 typedef long long LL;
 5 
 6 using namespace std;
 7 
 8 const double EPS = 1e-8;
 9 const int N = 510000;
10 const int INF = 0x3f3f3f3f;
11 
12 LL a[N], k;
13 int len;
14 
15 struct node
16 {
17     int l; //区间左端
18     LL sum;
19 }p[N];
20 
21 void Solve(int l, int r)
22 {
23     LL sum = 0, s = p[r].sum;
24     if(s < k)
25         return ;
26 
27     while(l < r)
28     {
29         sum += a[l];
30         if(s - sum >= k)
31         {
32             p[r].sum = s - sum;
33             p[r].l = l + 1; // 更新区间左端
34         }
35         l++;
36     }
37     len = min(len, r - p[r].l + 1);
38 }
39 
40 int main()
41 {
42     int t, n;
43     scanf("%d", &t);
44     while(t--)
45     {
46         memset(a, 0, sizeof(a));
47         memset(p, 0, sizeof(p));
48 
49         scanf("%d %lld", &n, &k);
50 
51         p[0].l = 1;
52         len = INF;
53 
54         for(int i = 1; i <= n; i++)
55         {
56             scanf("%lld", &a[i]);
57             if(p[i-1].sum > 0)
58             {
59                 p[i].sum = a[i] + p[i-1].sum;
60                 p[i].l = p[i-1].l;
61             }
62             else
63             {
64                 p[i].sum = a[i];
65                 p[i].l = i;
66             }
67             Solve(p[i].l, i);
68         }
69         if(len == INF) len = -1;
70         printf("%d
", len);
71     }
72 
73     return 0;
74 }

原文出处

永远渴望,大智若愚(stay hungry, stay foolish)
原文地址:https://www.cnblogs.com/h-hkai/p/8824361.html