lougu P2344奶牛抗議
阿新 • • 發佈:2018-11-01
nbsp ret 先來 希望 限制 i++ 位置 owb prot
題目背景
Generic Cow Protests, 2011 Feb
題目描述
約翰家的N 頭奶牛正在排隊遊行抗議。一些奶牛情緒激動,約翰測算下來,排在第i 位的奶牛的理智度為Ai,數字可正可負。
約翰希望奶牛在抗議時保持理性,為此,他打算將這條隊伍分割成幾個小組,每個抗議小組的理智度之和必須大於或等於零。奶牛的隊伍已經固定了前後順序,所以不能交換它們的位置,所以分在一個小組裏的奶牛必須是連續位置的。除此之外,分組多少組,每組分多少奶牛,都沒有限制。
約翰想知道有多少種分組的方案,由於答案可能很大,只要輸出答案除以1000000009 的余數即可。
首先來看直接DP是肯定過不了的
但是我們要先退出轉移方程,然後進行優化
dp[i]代表的是結尾為i的地方的方案數
轉移的話就是往前枚舉,直到和大於等於0
再之前之前的所有滿足數量加上來
這就正好可以用樹狀數組來維護
我們又發現,是否大於0,只和兩個數的大小有關,和具體的值無關,所以我們可以離散化
接下來動態維護就可以了
下面給出代碼:(沒有離散化,需要的自己寫)
#include<iostream> #include<algorithm> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #define mod 1000000009 using namespace std; inline int rd(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘; return x*f; } inline void write(int x){ if(x<0) putchar(‘-‘),x=-x;if(x>9) write(x/10); putchar(x%10+‘0‘); return ; } int c[10000006]; int n; int a[1000006]; int lowbit(int x){ return x&(-x); } void add(int i,int y){ for(;i<=10000000;i+=lowbit(i)) c[i]=(c[i]+y)%mod; } int solve(int i){ int sum=0; for(;i>=1;i-=lowbit(i)) sum=(sum+c[i])%mod; return sum%mod; } int f[100006]; int sum[100006],s[100006]; int main(){ freopen("01.in","r",stdin); n=rd(); for(int i=1;i<=n;i++){ a[i]=rd(); sum[i]=sum[i-1]+a[i]; } for(int i=1;i<=n;i++) sum[i]+=1000000; for(int i=1;i<=n;i++){ if(sum[i]>=0) f[i]=1; f[i]=(f[i]+solve(sum[i]))%mod; add(sum[i],f[i]%mod); } write(f[n]%mod); return 0; }
lougu P2344奶牛抗議