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 }

 

你可能感兴趣的:(part)