hdu 4193 Non-negative Partial Sums 单调队列
Problem Description
You are given a sequence of n numbers a0,..., an-1. A cyclic shift by k positions (0<=k<=n-1) results in the following sequence: ak ak+1,..., an-1, a0, a1,..., ak-1. How many of the n cyclic shifts satisfy the condition that the sum of the first i numbers is greater than or equal to zero for all i with 1<=i<=n?
Input
Each test case consists of two lines. The first contains the number n (1<=n<=106), the number of integers in the sequence. The second contains n integers a0,..., an-1 (-1000<=ai<=1000) representing the sequence of numbers. The input will finish with a line containing 0.
Output
For each test case, print one line with the number of cyclic shifts of the given sequence which satisfy the condition stated above.
Sample Input
3 2 2 1 3 -1 1 1 1 -1 0
Sample Output
3 2 0
方法 一
#include<iostream> #include<stdio.h> #include<cstring> #include<algorithm> using namespace std; int sum[2000006]; int sk[2000006]; int main( ) { int i,j,top,hid,N,val,res; while( scanf("%d",&N) && N ) { for( i = 1; i <= N; i++ ) { scanf("%d",&sum[i]); sum[i+N] = sum[i]; } for( i = 2; i <= N*2; i++ ) sum[i] += sum[i-1]; top = hid = 1; sk[1] = 1,res = 0; for( i = 2; i <= N*2; i++ ) { while( top <= hid && sum[i] < sum[sk[hid]] ) hid--; while( top <= hid && i > N && sk[top] + N < i ) top++; sk[++hid] = i; if( i > N && sum[sk[top]] - sum[i-N] >= 0 ) res++; } printf("%d\n",res); } //system("pause"); return 0; }
方法 二
#include<iostream> #include<stdio.h> #include<cstring> #include<algorithm> #include<cmath> using namespace std; struct point { int w,num; }q[1000006]; int val[1000006]; int Min[1000006]; bool cmp( point a,point b ) { return a.w < b.w; } int min( int a,int b ) { return a>b?b:a; } int main( ) { int N,i,k,ans; while( scanf("%d",&N) && N ) { val[0] = 0; Min[0] = 1000000001; for( i = 1; i <= N; i++ ) { scanf("%d",&val[i]); val[i] += val[i-1]; Min[i] = min( Min[i-1],val[i] ); q[i].w = val[i]; q[i].num = i; } sort( &q[1],&q[1] + N,cmp ); k = 1; ans = 0; for( i = 1; i <= N; i++ ) if( val[i] < 0 ) break; if( i == N + 1 ) ans++; for( i = 1; i < N; i++ ) { int sum = val[N] - val[i]; if( sum < 0 ) continue; int sta = i + 1; while( q[k].num < sta ) k++; if( k >= N + 1 ) break; if( q[k].w - val[i] < 0 ) continue; if( Min[i] + sum >= 0 ) ans++; } printf("%d\n",ans); } //system("pause"); return 0; }