【动态规划】【树状数组】[USACO2011 FEB]奶牛抗议

这道题目的关键就是想到用树状数组对DP进行优化,首先令f(i)表示分到第i个的时候子段和大于等于0的时候出现的最大的种树, 那么可以发现f(i)=f(j)|sum(i)sum(j)0那么后面的部分可以变成sum(i)sum(j)那么就可以使用树状数组进行维护,下标就是sum(j)存的就是f(j)因为sum(j)还是很大的所以离散化一下就好了。

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 100000;
const int MOD = 1e9+9;
int Tree[MAXN * 4+10], n, ls[MAXN+10], lLen, sum[MAXN+10];
int f[MAXN+10];
int bit(int u){return (u&(-u));}
void add(int u, int v){
    while(u <= lLen){
        Tree[u] = Tree[u] + v;
        Tree[u] %= MOD;
        u += bit(u);
    }
}
int query(int u){
    int ret = 0;
    while(u > 0){
        ret += Tree[u];
        ret %= MOD;
        u -= bit(u);
    }
    return ret;
}
int main(){
    int n;
    scanf("%d", &n);
    for(int i=1;i<=n;i++){
        scanf("%d", &sum[i]);
        sum[i] += sum[i-1];
        ls[i+1] = sum[i];
    }
    ls[1] = 0;
    sort(ls+1, ls+n+2);
    lLen = unique(ls+1, ls+n+2) - ls - 1;
    add(lower_bound(ls+1, ls+lLen+1, 0) - ls, 1);
    //printf("%d\n", query(1));
    for(int i=1;i<=n;i++){
        f[i] = query(lower_bound(ls+1, ls+lLen+1, sum[i]) - ls);
        add(lower_bound(ls+1, ls+lLen+1, sum[i]) - ls, f[i]);
    }
    printf("%d\n", f[n]);

    return 0;
}

posted on 2015-07-17 22:10  JeremyGuo  阅读(153)  评论(0编辑  收藏  举报

导航