Sereja has a sequence that consists of n positive integers, a1, a2, ..., an.
First Sereja took a piece of squared paper and wrote all distinct non-empty non-decreasing subsequences of sequence a. Then for each sequence written on the squared paper, Sereja wrote on a piece of lines paper all sequences that do not exceed it.
A sequence of positive integers x = x1, x2, ..., xr doesn't exceed a sequence of positive integers y = y1, y2, ..., yr, if the following inequation holds: x1 ≤ y1, x2 ≤ y2, ..., xr ≤ yr.
Now Sereja wonders, how many sequences are written on the lines piece of paper. Help Sereja, find the required quantity modulo 1000000007 (109 + 7).
The first line contains integer n (1 ≤ n ≤ 105). The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 106).
In the single line print the answer to the problem modulo 1000000007 (109 + 7).
1 42
42
3 1 2 2
13
5 1 2 3 4 5
719
题目大意:
求所有的非递减子串的价值和(子串需要保证没有重复数字),一个子串的价值为子串所有数字的乘积。
思路:
设定Dp【i】,表示以位子i作为子串的结尾能够获得的价值和。
那么有:Dp【i】=ΣDp【j】*Dp【i】+Dp【i】,这里需要保证a【j】<=a【i】,那么这里我们可以用树状数组加速转移。
因为子串需要保证没有重复数字,那么我们需要去重,Dp【i】-=Pre【a【i】】,pre【a【i】】表示上一次a【i】出现的位子能够提供的价值。
过程维护一下即可。
注意取模、
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
#define ll __int64
/**************************************/
ll n;
ll mod = 1000000000+7;
ll tree[3000005];//树
ll lowbit(ll x)//lowbit
{
return x&(-x);
}
ll sum(ll x)
{
ll sum=0;
while(x>0)
{
sum+=tree[x];
sum%=mod;
x-=lowbit(x);
}
return sum;
}
ll add(ll x,ll c)
{
while(x<=1000000+50)
{
tree[x]+=c;
tree[x]%=mod;
x+=lowbit(x);
}
}
/**************************************/
ll a[1050000];
ll dp[1050000];
ll pre[1050000];
int main()
{
while(~scanf("%I64d",&n))
{
ll ans=0;
memset(tree,0,sizeof(tree));
memset(pre,-1,sizeof(pre));
memset(dp,0,sizeof(dp));
for(ll i=1;i<=n;i++)scanf("%I64d",&a[i]);
for(ll i=1;i<=n;i++)
{
dp[i]=sum(a[i])*a[i]+a[i];
if(pre[a[i]]!=-1)dp[i]-=pre[a[i]];
dp[i]=(dp[i]%mod+mod)%mod;
ans+=dp[i];
ans=(ans%mod+mod)%mod;
pre[a[i]]=sum(a[i])*a[i]+a[i];
add(a[i],dp[i]);
}
printf("%I64d\n",(ans%mod+mod)%mod);
}
}

探讨了Sereja面对的一道算法题,要求找出所有非递减子序列及其组合的计数问题,并通过动态规划结合树状数组的方法解决了该问题。
1588

被折叠的 条评论
为什么被折叠?



