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 }