codeforces 314C Sereja and Subsequences(树状数组+DP)

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 modulo1000000007 (10^9 + 7).

Input

The first line contains integer n (1 ≤ n ≤ 10^5). The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 10^6).

Output

In the single line print the answer to the problem modulo 1000000007 (10^9 + 7).

 

题目大意:

  给定一个数组a:

  (1)定义某个序列a小于某个序列b当且仅当a[i]≤b[i]对所有i都成立;(2)写出a的不同的所有非下降子序列;(3)若每个不同的非下降子序列的所有小于它的序列数之和定义为f,求所有f的总和。

思路:

  若用s[i]表示以a[i]结尾的所有非下降子序列的f之和,那么设a[j]≤a[i]且j<i,那么s[i] = sum(s[j])*a[i] + a[i]。即在序列a[j]后接上一个a[i]可形成新的子序列。

  要维护一段数字的和,树状数组就派上用场了。

  这里还有一个问题,就是有可能多个a[i]相同,这样会导致重复计算。我们只需要把s[i]减去a[j]≤a[i]且j<i的sum(s[j])即可。

  比如要计算序列2 2 2的时候,s[1] = {a[1]},s[2] = {a[1,2]},s[3] = {a[1,2,3]}。此时s[i]准确表示为:以a[i]结尾的与i之前所有子序列都不同的所有非下降子序列的f之和。

 

 1 #include <cstdio>

 2 #include <algorithm>

 3 using namespace std;

 4 

 5 #define MOD 1000000007

 6 #define MAXN 100010

 7 

 8 struct node{

 9     int x, rank, pos;

10 } a[MAXN];

11 

12 bool cmpx(node a, node b){

13     return a.x < b.x;

14 }

15 

16 bool cmppos(node a, node b){

17     return a.pos < b.pos;

18 }

19 

20 int n, tot;

21 int b[MAXN], c[MAXN];

22 

23 inline int lowbit(int x){

24     return x&-x;

25 }

26 

27 inline int sum(int x){

28     int ans = 0;

29     while(x > 0){

30         ans = (ans + c[x])%MOD;

31         x -= lowbit(x);

32     }

33     return ans;

34 }

35 

36 inline void add(int i, int x){

37     while(i <= tot){

38         c[i] = (c[i] + x)%MOD;

39         i += lowbit(i);

40     }

41 }

42 

43 int main(){

44     scanf("%d", &n);

45     for(int i = 1; i <= n; ++i)

46         scanf("%d", &a[i].x), a[i].pos = i;

47     sort(a+1, a+n+1, cmpx);

48     tot = 1; a[1].rank = 1;

49     for(int i = 2; i <= n; ++i){

50         if(a[i].x != a[i-1].x) ++tot;

51         a[i].rank = tot;

52     }

53     sort(a+1, a+n+1, cmppos);

54     for(int i = 1; i <= n; ++i){

55         int tmp = ((long long)sum(a[i].rank) * a[i].x % MOD + a[i].x)%MOD;

56         add(a[i].rank, (tmp - b[a[i].rank] + MOD)%MOD);

57         b[a[i].rank] = tmp;

58     }

59     printf("%d\n",sum(tot));

60 }
AC 359ms

 

你可能感兴趣的:(codeforces)