CodeForces 314C Sereja and Subsequences :找出序列种所有不下降子序列,求出所有子序列乘积和 :技巧/树状数组

树状数组数组里面记录的值是当前以a[i]结尾的乘积和=

比如当前到i的a[i],查询1-a[i]的所有值和,乘以(a[i]+1)就是当前以a[i]为结尾的乘积和=

这样出现了重复计算的情况,只要减去上一次a[i]结尾的乘积和即可

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 #define LL long long
 6 const LL MOD=1e9+7;
 7 LL m,dp[1000005],a[100005];
 8 LL sum(LL x)
 9 {
10   LL ret=0;
11   while (x>0){
12     ret=(ret+dp[x])%MOD;
13     x-=x&-x;
14   }
15   return ret;
16 }
17 void add(LL x,LL y)
18 {
19   while (x<=m){
20     dp[x]=(dp[x]+y)%MOD;
21     x+=x&-x;
22   }
23 }
24 int main()
25 {
26   LL n,i,ans,t1,t2,val;
27   m=ans=0;
28   scanf("%I64d",&n);
29   for (i=1;i<=n;i++){
30        scanf("%I64d",&a[i]);
31     m=max(m,a[i]);
32   }
33   memset(dp,0,sizeof(dp));
34   for (i=1;i<=n;i++)
35   {
36     t1=sum(a[i]); t2=sum(a[i]-1);
37     val=((t1+1)*a[i]-(t1-t2+MOD)%MOD)%MOD;
38     add(a[i],val);
39     ans=(ans+val)%MOD;
40   }
41   printf("%I64d\n",ans);
42   return 0;
43 }
View Code

题目链接:http://codeforces.com/problemset/problem/314/C

posted on 2015-03-27 16:54  xiao_xin  阅读(345)  评论(0编辑  收藏  举报

导航