hihocoder1475 数组分拆【DP+前缀和优化】

思路:

DP[ i ] 代表以 i 结尾的方案数. dp[i] += sum[i] - sum[j - 1] != 0 ? dp[j] : 0 ;

对于100%的数据,满足1<=N<=105, |Ai|<=100
n 1e5呀,两层for,GG;
利用树状数组维护sum[i],存的是以sum[i]的方案数 ,
那么每次加上当前所有的方案,减去sum[i]的方案,就好了。
这里还有一个小问题就是 |sum[i]|<=1e7,所以先离散化一下就好了。
把当前所有前缀和的方案数加起来。。然后减掉以自己的方案数。

也可以用map.


树状数组维护。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
const int N=1e5+10;
LL sval[N],sum[N];
LL dp[N];
int lowbit(int x)
{
    return x&(-x);
}
LL Sum(int d)
{
    LL ans=0;
    while(d)
    {
        ans=(ans+sval[d])%mod;
        d=d-lowbit(d);
    }
    return ans;
}

void add(int d,LL val,int n)
{
    while(d<=n)
    {
        sval[d]=(sval[d]+val)%mod;
        d+=lowbit(d);
    }
}

vector<LL>xs;
int main()
{
    LL n,a;
    scanf("%lld",&n);
    sum[0]=0;
    xs.push_back(0);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a);
        sum[i]=sum[i-1]+a;
        xs.push_back(sum[i]);
    }
    sort(xs.begin(),xs.end());
    auto it=unique(xs.begin(),xs.end());
    for(int i=0;i<=n;i++)
        sum[i]=lower_bound(xs.begin(),it,sum[i])-xs.begin()+1;
    memset(dp,0,sizeof(dp));
    for(int i=0;i<=n;i++)
    {
        dp[i]+=Sum(xs.size());
        dp[i]-=Sum(sum[i])-Sum(sum[i]-1);
        dp[i]=(dp[i]+mod)%mod;
        if(dp[i]==0)
            dp[i]=1;
        add(sum[i],dp[i],xs.size());
    }
    printf("%lld\n",dp[n]);
    return 0;
}


map维护

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
const int N=1e5+10;
LL sum[N];
LL dp[N];
map<int,int>mp;

int main()
{
    LL n,a;
    scanf("%lld",&n);
    sum[0]=0;
    mp.clear();
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a);
        sum[i]=sum[i-1]+a;
    }
    memset(dp,0,sizeof(dp));
    dp[0]=1;
    mp[0]=1;
    LL cnt=1;
    for(int i=1;i<=n;i++)
    {
        if(!mp.count(sum[i]))
        {
            dp[i]=cnt;
            mp[sum[i]]=dp[i];
        }
        else
        {
            dp[i]=((cnt-mp[sum[i]])%mod+mod)%mod;
            mp[sum[i]]=(mp[sum[i]]+dp[i]+mod)%mod;
        }
        cnt=(cnt+dp[i]+mod)%mod;
    }
    printf("%lld\n",dp[n]);
    return 0;
}



posted @ 2017-03-05 18:28  see_you_later  阅读(222)  评论(0编辑  收藏  举报