lougu P2344奶牛抗議


題目背景

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;
}

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com