zoukankan      html  css  js  c++  java
  • HDU 2227 Find the nondecreasing subsequences(dp+线段树维护)

    Find the nondecreasing subsequences

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2225    Accepted Submission(s): 862


    Problem Description
    How many nondecreasing subsequences can you find in the sequence S = {s1, s2, s3, ...., sn} ? For example, we assume that S = {1, 2, 3}, and you can find seven nondecreasing subsequences, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}.
     
    Input
    The input consists of multiple test cases. Each case begins with a line containing a positive integer n that is the length of the sequence S, the next line contains n integers {s1, s2, s3, ...., sn}, 1 <= n <= 100000, 0 <= si <= 2^31.
     
    Output
    For each test case, output one line containing the number of nondecreasing subsequences you can find from the sequence S, the answer should % 1000000007.
     
    Sample Input
    3 1 2 3
     
    Sample Output
    7
     
    题目意思很简单,一句话,对于问题规模为10w求出所有非递减子序列的数量。
    dp的状态转移方程即为 dp[j] = (Σ(i from 1 ~ j-1 && h[i]<=h[j])dp[i])+1
    然后得到一个 O(n²)的算法,这样肯定是过不去的。
    然后队友教我用线段树去维护。
    求dp[j]时,需要求之前所有下标高度小于h[j] 的dp[i]之和。
    可以发现 dp[i] i ∈ {i|i<j and h[i] <= h[j]}
    所以只要对h[N]进行一次排序,得到h[i]到新下标的映射, (他们管这个叫离散化)
    再从前向后扫一边h[N]即可保证i集合的条件。
    说了这么多不如直接看代码。
    由于有线段树维护 复杂度削减至 O(n log(n))
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <unordered_map>
    #include <set>
    #include <map>
    
    using namespace std;
    const unsigned int N = 100005;
    typedef long long ll;
    typedef unsigned int iu;
    const int mod = 1000000007;
    ll dp[N<<2u];
    void build(iu l,iu r,iu rt){
        dp[rt] = 0;
        if(l==r){
            return;
        }
        iu m = (l+r)>>1u;
        build(l,m,rt<<1u);
        build(m+1,r,rt<<1u|1u);
    }
    void pushUp(iu rt){
        dp[rt] = (dp[rt<<1u]+dp[rt<<1u|1u])%mod;
    }
    ll query(iu L,iu R ,iu l,iu r,iu rt){
        if(L <= l and r <= R){
            return dp[rt];
        }
        iu m = (l+r)>>1u;
        ll ans = 0;
        if(m>=L)ans=query(L,R,l,m,rt<<1u);
        if(m<R)ans+=query(L,R,m+1,r,rt<<1u|1u);
        return ans%mod;
    }
    void upDate(iu loc,ll val,iu l,iu r,iu rt){
        if(l==r){
            dp[rt]+=val;
            dp[rt]%=mod;
            return;
        }
        iu m = (l+r)>>1u;
        if(m>=loc)upDate(loc,val,l,m,rt<<1u);
        if(m<loc)upDate(loc,val,m+1,r,rt<<1u|1u);
        pushUp(rt);
    }
    map<ll,iu>reflect;///unordered_map 用迭代器访问不一定有序;
    ll h[N];
    int main(){
        int n;
        while (cin>>n){
            reflect.clear();
            for(int i = 1 ; i <= n ; ++i){
                scanf("%lld",h+i);
                reflect[h[i]] = 0;
            }
            iu cnt = 0;
            for(auto &i :reflect){///细节 auto i : reflect 无法更改其中数值
                i.second = ++cnt;
            }
            iu k = reflect.size();
            build(1,k,1);
            long long ans ;
            for(int i = 1 ; i <= n ; ++i){
                iu pos = reflect[h[i]];
                ans = query(1,pos,1,k,1);
                upDate(pos,ans+1,1,k,1);
            }
            printf("%lld
    ",query(1,k,1,k,1));
        }
    }

    数据结构真有意思;

    另外HDU 3607和本题类似不妨一做

    HDU 3607 题解传送门

    https://www.cnblogs.com/xusirui/p/9396145.html

  • 相关阅读:
    C语言寒假大作战01
    第十二次作业
    第十一次作业
    第十周作业
    第九次作业
    第8周作业
    第七次作业
    C语言I作业12—学期总结
    第一周作业
    C语言l博客作业02
  • 原文地址:https://www.cnblogs.com/DevilInChina/p/9399687.html
Copyright © 2011-2022 走看看