zoukankan      html  css  js  c++  java
  • 【bzoj5157】[Tjoi2014]上升子序列 树状数组

    题目描述

    求一个数列本质不同的至少含有两个元素的上升子序列数目模10^9+7的结果。


    题解

    树状数组

    傻逼题,离散化后直接使用树状数组统计即可。由于要求本质不同,因此一个数要减去它前一次出现时的贡献(即以它上一次出现的位置为最后一个元素的上升子序列数目)统计到答案中。

    由于要包含至少两个元素,因此还需要减掉不同数的数目。

    时间复杂度 $O(nlog n)$ 

    #include <cstdio>
    #include <algorithm>
    #define N 100010
    #define mod 1000000007
    using namespace std;
    int n , a[N] , v[N] , pos[N] , last[N] , val[N] , f[N];
    inline void add(int x , int a)
    {
        int i;
        for(i = x ; i <= n ; i += i & -i)
            f[i] = (f[i] + a) % mod;
    }
    inline int query(int x)
    {
        int i , ans = 0;
        for(i = x ; i ; i -= i & -i)
            ans = (ans + f[i]) % mod;
        return ans;
    }
    int main()
    {
        int i , sum = 0;
        scanf("%d" , &n);
        for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , v[i] = a[i];
        sort(v + 1 , v + n + 1);
        for(i = 1 ; i <= n ; i ++ )
        {
            a[i] = lower_bound(v + 1 , v + n + 1 , a[i]) - v;
            if(!pos[a[i]]) sum ++ ;
            last[i] = pos[a[i]] , pos[a[i]] = i;
        }
        for(i = 1 ; i <= n ; i ++ ) val[i] = query(a[i] - 1) + 1 , add(a[i] , (val[i] - val[last[i]] + mod) % mod);
        printf("%d
    " , (query(n) - sum + mod) % mod);
        return 0;
    }
    
  • 相关阅读:
    关于p标签
    用unescape反编码得出汉字
    一个未知高度垂直居中的简单方法
    发现个div float的小秘密
    w3cschool关于list-style-position时的另外发现
    oracle 11gR2默认密码修改
    程序员的十楼层。看看自己在第几层
    Steve Yegge:Google面试秘籍
    为学Linux,我看了这些书
    程序员的困境
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8461609.html
Copyright © 2011-2022 走看看