zoukankan      html  css  js  c++  java
  • 51nod 1376 最长递增子序列的数量(线段树)

    51nod 1376 最长递增子序列的数量

    数组A包含N个整数(可能包含相同的值)。设S为A的子序列且S中的元素是递增的,则S为A的递增子序列。如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS)。A的LIS可能有很多个。例如A为:{1 3 2 0 4},1 3 4,1 2 4均为A的LIS。给出数组A,求A的LIS有多少个。由于数量很大,输出Mod 1000000007的结果即可。相同的数字在不同的位置,算作不同的,例如 {1 1 2} 答案为2。
     
    Input
    第1行:1个数N,表示数组的长度。(1 <= N <= 50000)
    第2 - N + 1行:每行1个数A[i],表示数组的元素(0 <= A[i] <= 10^9)
    Output
    输出最长递增子序列的数量Mod 1000000007。
    Input示例
    5
    1
    3
    2
    0
    4
    Output示例
    2
    /*
    51nod 1376 最长递增子序列的数量
    
    problem:
    给你一个数组,求其中最长递增子序列有多少个
    
    solve:
    对于第i个数a[i]而言,它需要知道已经出现的[1,a[i]-1]中最长递增子序列的长度以及数量. 所以可以利用线段树来维护,
    然后利用长度和数量来更新a[i]
    
    hhh-2016/09/03-16:41:1
    */
    #pragma comment(linker,"/STACK:124000000,124000000")
    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <math.h>
    #include <queue>
    #include <set>
    #include <map>
    #define lson  i<<1
    #define rson  i<<1|1
    #define ll long long
    #define clr(a,b) memset(a,b,sizeof(a))
    #define scanfi(a) scanf("%d",&a)
    #define scanfs(a) scanf("%s",a)
    #define scanfl(a) scanf("%I64d",&a)
    #define scanfd(a) scanf("%lf",&a)
    #define key_val ch[ch[root][1]][0]
    #define eps 1e-7
    #define inf 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const ll mod = 1000000007;
    const int maxn = 50010;
    const double PI = acos(-1.0);
    int a[maxn],t[maxn];
    struct node
    {
        int l,r;
        ll Max,num;
        int mid;
    } tree[maxn << 2];
    
    void push_up(int i)
    {
        if(tree[lson].Max == tree[rson].Max)
        {
            tree[i].Max = tree[lson].Max;
            tree[i].num = tree[lson].num + tree[rson].num;
            tree[i].num %= mod;
        }
        else if(tree[lson].Max > tree[rson].Max)
        {
            tree[i].Max = tree[lson].Max;
            tree[i].num = tree[lson].num;
        }
        else
        {
            tree[i].Max = tree[rson].Max;
            tree[i].num = tree[rson].num;
        }
    }
    
    void build(int i,int l,int r)
    {
        tree[i].l = l,tree[i].r = r;
        tree[i].Max = tree[i].num = 0;
        tree[i].mid = (l+r) >> 1;
        if(l == r)
            return ;
        build(lson,l,tree[i].mid);
        build(rson,tree[i].mid + 1,r);
        push_up(i);
    }
    
    void push_down(int i)
    {
    
    }
    
    void update(int i,int k,ll len,ll many)
    {
        if(tree[i].l == tree[i].r && tree[i].l == k)
        {
            if(tree[i].Max < len) tree[i].Max = len,tree[i].num = many;
            else if(tree[i].Max == len) tree[i].num += many;
            tree[i].num %= mod;
            return ;
        }
        int mid = tree[i].mid;
        if(k <= mid)
            update(lson,k,len,many);
        else update(rson,k,len,many);
        push_up(i);
    }
    ll tans,tnum;
    void query(int i,int l,int r)
    {
        if(l > r)
        {
            tans = 0,tnum = 1;
            return ;
        }
        if(tree[i].l >= l && tree[i].r <= r)
        {
            if(tans == -1)
                tans = tree[i].Max,tnum = tree[i].num;
            else
            {
                if(tans == tree[i].Max) tnum += tree[i].num;
                else if(tans < tree[i].Max)
                {
                    tans = tree[i].Max,tnum = tree[i].num;
                }
                tnum %= mod;
            }
            return ;
        }
        push_down(i);
        int mid = tree[i].mid;
        if(l <= mid)
            query(lson,l,r);
        if(r > mid)
            query(rson,l,r);
        return;
    }
    
    int cnt = 0;
    int main()
    {
        int n;
        while(scanfi(n) != EOF)
        {
            for(int i = 0; i< n;i++){
                scanfi(a[i]);
                t[i] = a[i];
            }
            sort(a,a+n);
            cnt = 0;
            for(int i = 1;i < n;i++)
            {
                if(a[i] != a[cnt])
                a[++cnt] = a[i];
            }
    //        for(int i = 0;i <= cnt;i++)
    //            printf("%d
    ",a[i]);
            build(1,0,cnt);
            ll tMax = 0,ans = 0;
            int id = lower_bound(a,a+cnt+1,t[0]) -a;
            update(1,id,1,1);
            tMax = 1,ans = 1;
            for(int i = 1;i < n;i++)
            {
                id = lower_bound(a,a+cnt+1,t[i]) -a;
    //            cout << id <<" " ;
                tans = -1,tnum = 0;
                query(1,0,id-1);
                if(!tans && !tnum)
                    tnum = 1;
                if(tMax < tans+ 1) tMax = tans+1,ans = tnum;
                else if(tMax == tans+1) ans += tnum;
                ans %= mod;
                update(1,id,tans + 1,tnum);
            }
    //        cout <<endl;
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    关于网络安全攻防演化博弈的研究小议
    入侵检测技术框架总论【课题笔记】
    态势提取的前置基础技术:数据集成、数据规约、数据融合
    网络安全态势感知框架小议
    入侵检测基本准则(Basic principles of intrusion detection)【v1.0】
    Research on collection technology and countermeasure technology of system behavior log for HIDS,面向HIDS的日志采集技术与对抗技术研究
    Tomcat(二):Tomcat处理一个Http请求
    Tomcat(一):Tomcat启动时加载web.xml
    SpringMVC(十七):Web.xml初始化流程源码分析
    设计模式(九)责任链(Chain of Responsibility)
  • 原文地址:https://www.cnblogs.com/Przz/p/5837488.html
Copyright © 2011-2022 走看看