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 }