BZOJ2274: [Usaco2011 Feb]Generic Cow Protests
2274: [Usaco2011 Feb]Generic Cow Protests
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 196 Solved: 122
[Submit][Status]
Description
Farmer John's N (1 <= N <= 100,000) cows are lined up in a row and
numbered 1..N. The cows are conducting another one of their strange
protests, so each cow i is holding up a sign with an integer A_i
(-10,000 <= A_i <= 10,000).
FJ knows the mob of cows will behave if they are properly grouped
and thus would like to arrange the cows into one or more contiguous
groups so that every cow is in exactly one group and that every
group has a nonnegative sum.
Help him count the number of ways he can do this, modulo 1,000,000,009.
By way of example, if N = 4 and the cows' signs are 2, 3, -3, and
1, then the following are the only four valid ways of arranging the
cows:
(2 3 -3 1)
(2 3 -3) (1)
(2) (3 -3 1)
(2) (3 -3) (1)
Note that this example demonstrates the rule for counting different
orders of the arrangements.
给出n个数,问有几种划分方案(不能改变数的位置),使得每组中数的和大于等于0。输出方案数除以 1000000009的余数。
Input
* Line 1: A single integer: N
* Lines 2..N + 1: Line i + 1 contains a single integer: A_i
Output
* Line 1: A single integer, the number of arrangements modulo
1,000,000,009.
Sample Input
2
3
-3
1
Sample Output
HINT
Source
题解:
比较好的一道题。
刚开始看了没思路,后来想了想发现i+1 到 j 可以分一段等价与 s[i]>=s[j]
然后设 f[i]表示前 i 个数能分成的方案数,然后那么 f[i]=sigma(f[j]) s[i]>=s[j] 初值f[0]=1
然后我们发现这样暴力做的话是n^2的,那么考虑优化
既然 s[i]>=s[j] 时 f[j]才可以更新 f[i],那我们换一个思路来考虑,另 g[i] 表示前缀和第 i 大的前缀可以划分的方案总数
那么 f[i]=sigma(g[j]) 1<=j<=s[i] 然后还要给 g[s[i]]+=f[i]
想到了什么?对了,就是树状数组。
离散化一下,然后注意一下边界就可以过了。
status没rank1表示很桑心
代码:
1 #include<cstdio> 2 3 #include<cstdlib> 4 5 #include<cmath> 6 7 #include<cstring> 8 9 #include<algorithm> 10 11 #include<iostream> 12 13 #include<vector> 14 15 #include<map> 16 17 #include<set> 18 19 #include<queue> 20 21 #include<string> 22 23 #define inf 1000000000 24 25 #define maxn 150000 26 27 #define maxm 500+100 28 29 #define eps 1e-10 30 31 #define ll long long 32 33 #define pa pair<int,int> 34 35 #define for0(i,n) for(int i=0;i<=(n);i++) 36 37 #define for1(i,n) for(int i=1;i<=(n);i++) 38 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 40 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 42 43 #define mod 1000000009 44 45 using namespace std; 46 47 inline int read() 48 49 { 50 51 int x=0,f=1;char ch=getchar(); 52 53 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 54 55 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 56 57 return x*f; 58 59 } 60 int n,tot,s[maxn],a[maxn],c[maxn]; 61 struct rec{int x,y;}b[maxn]; 62 inline void change(int x,int y) 63 { 64 if(!y)return; 65 for(;x<=tot;x+=x&(-x))s[x]=(s[x]+y)%mod; 66 } 67 inline int sum(int x) 68 { 69 int t=0; 70 for(;x;x-=x&(-x))t=(t+s[x])%mod; 71 return t; 72 } 73 inline bool cmp(rec a,rec b){return a.x<b.x;} 74 75 int main() 76 77 { 78 79 freopen("input.txt","r",stdin); 80 81 freopen("output.txt","w",stdout); 82 83 n=read(); 84 for1(i,n)a[i]=a[i-1]+read(),b[i].x=a[i],b[i].y=i; 85 sort(b,b+n+1,cmp); 86 tot=0; 87 for0(i,n) 88 { 89 if(i==0||b[i].x!=b[i-1].x)tot++; 90 c[b[i].y]=tot; 91 } 92 change(c[0],1); 93 for1(i,n-1)change(c[i],sum(c[i])); 94 printf("%d\n",sum(c[n])); 95 96 return 0; 97 98 }