hdu 4193 Non-negative Partial Sums

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4193

题意:给出一个n数列,要求把前i(1<=i<=n)个数移到剩余数列的后面形成新的数列,如果新数列满足前i(1<=i<=n)个数均大于等于0,算一种情况,问总共有多少种情况。

简单思路:单调队列+前缀和,枚举每一个可能的以i为首的数列,用单调队列找出区间[i,i+n-1]的最小前缀和,如果最小前缀和sum[k]-sum[i-1]>=0,就可能算一种,并在枚举的时候更新单调队列。

总结:1.昨天比赛训练的时候没有想到单调队列的做法,简单的前缀和果然的超时了,学过的算法及思维远远不够,因为貌似这道题去年我做过,囧。。。

         2.如果单调队列加上结构体得2000+ms,我的挫代码就如此,菜。应该就在前缀和数组sum[]上面进行单调会快一点吧。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #define inf 0x7fffffff
 9 using namespace std;
10 const int maxn=1000000+10;
11 struct node
12 {
13     int value;
14     int tag;
15     node () {tag=0;value=0; }
16 }q[maxn*2];
17 int sum[maxn*2];
18 int an[maxn*2];
19 int main()
20 {
21     int n;
22 
23     while (cin>>n,n)
24     {
25         memset(sum,0,sizeof(sum));
26         for (int i=1 ;i<=n ;i++)
27         {
28             scanf("%d",&an[i]);
29             an[n+i]=an[i];
30         }
31         for (int i=1 ;i<=2*n ;i++) sum[i]=sum[i-1]+an[i];
32         int h=1,r=0;
33         for (int i=1 ;i<n ;i++)
34         {
35             while (h<=r && q[r].value>=sum[i]) r--;
36             q[++r].value=sum[i];
37             q[r].tag=i;
38         }
39         int count=0;
40         for (int i=n ;i<2*n ;i++)
41         {
42             while (h<=r && q[r].value>=sum[i]) r--;
43             q[++r].value=sum[i];
44             q[r].tag=i;
45 
46             while (h<=r && q[h].tag<i-n+1) h++;
47             if (q[h].value-sum[i-n] >=0) count++;
48         }
49         cout<<count<<endl;
50     }
51     return 0;
52 }

 

posted @ 2014-03-16 09:36  huangxf  阅读(285)  评论(0编辑  收藏  举报