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;
    }
    
  • 相关阅读:
    列表框JList 及动作监听
    WindowListener(附带适配器改良方案)
    常用的几种文本组件(JTextComponent)
    JToggleButton组件
    java实现鼠标拖拽动作监听
    Flex读文本文件
    WPF socket通讯 UDP接收消息
    在线签名,并保存到本地
    flex直接访问服务器
    windows 8各种流之间的转换
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8461609.html
Copyright © 2011-2022 走看看