zoukankan      html  css  js  c++  java
  • UVALive_5825

    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;
    }

     

  • 相关阅读:
    小阳买水果
    单调队列+dp
    最长的合法序列(栈+dp)
    A. 打印收费
    数位dp(K好数)
    Floyd(选地址)
    最短路计数
    线段树维护区间01
    解密(拓展欧几里的)
    树、森林的遍历
  • 原文地址:https://www.cnblogs.com/staginner/p/2402884.html
Copyright © 2011-2022 走看看