HDU 4193

来源:互联网 发布:sra数据上传 编辑:程序博客网 时间:2024/06/07 06:20

单调队列:队首元素总是队列最小值。

此题就是把序列a先转换成前n项和,因为是循环的,所以长度为2n,然后判断一个长度为n的子序列前缀和都大于等于0,即此段序列的最小值-队列前面的和=这段序列最小的前缀和。

#include<bits/stdc++.h>using namespace std;#define MAX 1000000int sum[MAX*2+1];int mq[MAX+1];int rear,frot;int n;void push(int i){    while(rear!=frot && sum[mq[rear-1]] > sum[i])        rear--;    mq[rear++]=i;}int main(){    while(scanf("%d",&n)&&n)    {        for(int i=1;i<=n;i++){            scanf("%d",&sum[i]);            sum[n+i]=sum[i];        }        for(int i=2;i<=2*n;i++){            sum[i]+=sum[i-1];        }//        for(int i=1;i<=n*2;i++){//            printf("%d ",sum[i]);//        }printf("\n");        rear=frot=0;        for(int i=1;i<n;i++){            push(i);        }//        for(int i=0;i<5;i++) {//            printf("%d ",mq[i]);//        } printf("\n");        int cot=0;        for(int i=n;i<2*n;i++){            push(i);            if(mq[frot] + n - 1 < i){                frot++;            }              if(sum[mq[frot]]-sum[i-n]>=0) cot++;        }        printf("%d\n",cot);    }    return 0;}/*5-10 3 -1 5 4*/


0 0
原创粉丝点击