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\n",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\n",ans);
    }
    return 0;
}

  

时间: 2024-11-03 05:42:31

51nod 1376 最长递增子序列的数量(线段树)的相关文章

51nod 1376: 最长递增子序列的数量(二维偏序+cdq分治)

1376 最长递增子序列的数量 Time Limit: 1 Sec Memory Limit: 128MB 分值: 160 难度:6级算法题 Description 数组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 1

51nod 1376 最长递增子序列的数量(不是dp哦,线段树 + &#160;思维)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376 题解:显然这题暴力的方法很容易想到就是以每个数为结尾最长的有多少个,但是这样显然会超时所以要想一个方法去优化,要么用stl要么就是数据结构 线段树是个可以考虑的对象因为这也是求区间的和于是稍微将原数组优化一下,按照大小排序一下然后再按照下标更新这样能确保有序.具体看一下代码 还有一点要提一下有时候要考虑两维的东西可以适当排一下序使其变成一维有序这样就方

51NOD 1376 最长递增子序列的数量 dp+BIT

题目链接:点这里!! 题意:中文题 题解: f[i]:以第i个数结尾的LIS的长度,和该长度的LIS数量  转移的话,显然f[i].first=max{f[j].first}+1,j<i且a[j]<a[i]  f[i].second=∑jf[j].second,f[j].first=f[i].first−1  我们可以用BIT来优化这个转移,维护≤i的最大长度和对应数量 #include<bits/stdc++.h> using namespace std; #pragma com

【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 <

51nod1376 最长递增子序列的数量

O(n2)显然超时.网上找的题解都是用奇怪的姿势写看不懂TAT.然后自己YY.要求a[i]之前最大的是多少且最大的有多少个.那么线段树维护两个值,一个是当前区间的最大值一个是当前区间最大值的数量那么我们可以做到O(logn)查询最大值和更新. 不过树状数组一直不怎么会用... #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std;

[2016-05-11][51nod][1134 最长递增子序列]

时间:2016-05-11 14:16:50 星期三 题目编号:[2016-05-11][51nod][1134 最长递增子序列] 题目大意:给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 分析: 维护一个栈,如果是更大值,加入栈顶,否则,替换栈内第一个不小于它的数字 #include<stdio.h> #include<algorithm> #include<string.h> using namespace std; co

51nod 1134 最长递增子序列

给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输出最长递增子序列的长度. Input示例 8 5 1 6 8 2 4 5 10 Output示例 5 //第一种做法,放

51nod 1134 最长递增子序列 (O(nlogn)算法)

1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输

LCS 51Nod 1134 最长递增子序列

给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输出最长递增子序列的长度. Input示例 8 5 1 6 8 2 4 5 10 Output示例 5 #include