随笔 - 843,  文章 - 0,  评论 - 214,  阅读 - 38万

UVALive_5825

    一个可行的思路就是扫描一遍,求出以i为左端点的且长度不超过N的区间和的最小值,如果这个最小值都大于或等于0的话,那么显然以i为左端点就是可行的。

    既然是区间求和,那么一般来说用前缀和比较方便,这样实际上对于每个i我们就是去找满足j>i&&j<=i+N的最小的A[j],其中A[]表示前缀和。

    我是用后缀和做的,如果用后缀和的话结论类似。

复制代码
#include<stdio.h>
#include<string.h>
#define MAXD 2000010
#define INF 0x7fffffff
int N, M, A[MAXD], a[MAXD], q[MAXD];
void init()
{
int i, j, k;
for(i = 1; i <= N; i ++)
scanf("%d", &a[i]);
for(i = N + 1; i <= (N << 1); i ++)
a[i] = a[i - N];
A[2 * N + 1] = 0;
for(i = 2 * N; i > 0; i --)
A[i] = A[i + 1] + a[i];
}
void solve()
{
int i, j, k, front, rear, ans;
front = rear = ans = 0;
for(i = 2; i <= N; i ++)
{
while(front < rear && A[i] > A[q[rear - 1]])
-- rear;
q[rear ++] = i;
}
for(i = 1; i <= N; i ++)
{
k = i + N;
while(front < rear && q[front] <= i)
++ front;
while(front < rear && A[k] > A[q[rear - 1]])
-- rear;
q[rear ++] = k;
if((long long int)A[i] - A[q[front]] >= 0)
++ ans;
}
printf("%d\n", ans);
}
int main()
{
for(;;)
{
scanf("%d", &N);
if(!N)
break;
init();
solve();
}
return 0;
}
复制代码

 

posted on   Staginner  阅读(196)  评论(0编辑  收藏  举报
< 2012年3月 >
26 27 28 29 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
1 2 3 4 5 6 7

点击右上角即可分享
微信分享提示