• 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
  • 相关阅读:
    sql server 日期
    restore database
    7.1设计并实现有理数库,使用整数表示分子和分母,完成有理数的加减乘除与化简运算
    6.2写search函数对已经排好的n个元素的整数数组a,查找整数key。
    6.1写sort函数对n个元素的整数数组n,按从小到大排序
    5.2将随机数模拟为不含大小王的扑克牌
    实现一个随机数库
    5.1写函数,返回1~52之间的随机数
    4.2分别使用循环和递归两种策略求二项式从c(n,k);
    4.1将某个大于1的自然数n分解为其素因子的乘积
  • 原文地址:https://www.cnblogs.com/oyking/p/3132668.html
Copyright © 2020-2023  润新知