题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376

1376 最长递增子序列的数量

基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题

收藏

关注

数组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

题解:

1.由于要统计个数,所以就不能用之前所谓的O(n^2)或O(nlogn)方法(这两种方法求的是LIS的长度,而不是个数)。

2.因此需要利用线段树进行统计:将输入的值进行离散化,然后在离散化后数组之上建立线段树(即以值建树而不是以下标建树)。线段树的每个结点需要记录两个信息: 该段的LIS的长度及个数。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 5e4+; pair<int,int> getMax(pair<int,int> x, pair<int,int>y)
{
if(x.first<y.first) x = y;
else if(x.first==y.first) x.second = (x.second+y.second)%MOD;
return x;
} pair<int,int> len[MAXN*];
void build(int u, int l, int r)
{
if(l==r)
{
len[u].first = len[u].second = ;
return;
}
int mid = (l+r)>>;
build(u*,l,mid);
build(u*+,mid+,r);
len[u] = getMax(len[u*],len[u*+]);
} void add(int u, int l, int r, int pos, pair<int,int> val)
{
if(l==r)
{
len[u] = getMax(len[u],val);
return;
}
int mid = (l+r)>>;
if(pos<=mid) add(u*,l,mid,pos,val);
else add(u*+,mid+,r,pos,val);
len[u] = getMax(len[u*],len[u*+]);
} pair<int,int> query(int u, int l, int r, int x, int y)
{
if(x<=l&&r<=y) return len[u]; int mid = (l+r)>>;
pair<int,int> ret = make_pair(,);
if(x<=mid) ret = getMax(ret,query(u*,l,mid,x,y));
if(y>=mid+) ret = getMax(ret,query(u*+,mid+,r,x,y));
return ret;
} int a[MAXN], M[MAXN], m;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i = ; i<=n; i++)
scanf("%d",&a[i]); memcpy(M+,a+,n*sizeof(a[]));
M[n+] = -INF; //在最前面加个无穷小,防止区间溢出
sort(M+,M++n+); //离散化
m = unique(M+,M++n+)-(M+); build(,,m);
for(int i = ; i<=n; i++)
{
int pos = lower_bound(M+,M++m,a[i])-(M+); //找到a[i]的上一个值的位置(这也是为什么要在离散化数组里加个无穷小)
pair<int,int> t = query(,,m,,pos);
if(t.first==) t.first = t.second = ; //如果在前面没人比它小,则自己作为第一个
else t.first++; //如果前面有人比它小,则长度+1(加上自己)
add(,,m,pos+,t); //插入
}
printf("%d\n", query(,,m,,m).second);
}
}

51Nod 1376 最长递增子序列的数量 —— LIS、线段树的更多相关文章

  1. 51nod 1376 最长递增子序列的数量(线段树)

    51nod 1376 最长递增子序列的数量 数组A包含N个整数(可能包含相同的值).设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递 ...

  2. 51NOD 1376 最长递增子序列的数量 [CDQ分治]

    1376 最长递增子序列的数量 首先可以用线段树优化$DP$做,转移时取$0...a[i]$的最大$f$值 但我要练习$CDQ$ $LIS$是二维偏序问题,偏序关系是$i<j,\ a_i< ...

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

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376 题解:显然这题暴力的方法很容易想到就是以每个数为结尾最 ...

  4. 51Nod 1376 最长递增子序列的数量 (DP+BIT)

    题意:略. 析:dp[i] 表示以第 i 个数结尾的LIS的长度和数量,状态方程很好转移,先说长度 dp[i] = max { dp[j] + 1 | a[i] > a[j] && ...

  5. 51nod 1376 最长上升子序列的数量 | DP | vector怒刷存在感!

    51nod 1376 最长上升子序列的数量 题解 我们设lis[i]为以位置i结尾的最长上升子序列长度,dp[i]为以位置i结尾的最长上升子序列数量. 显然,dp[i]要从前面的一些位置(设为位置j) ...

  6. 【51nod】1376 最长递增子序列的数量

    数组A包含N个整数(可能包含相同的值).设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可能有很多个. ...

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

    O(n2)显然超时.网上找的题解都是用奇怪的姿势写看不懂TAT.然后自己YY.要求a[i]之前最大的是多少且最大的有多少个.那么线段树维护两个值,一个是当前区间的最大值一个是当前区间最大值的数量那么我 ...

  8. 51nod 1134 最长递增子序列

    题目链接:51nod 1134 最长递增子序列 #include<cstdio> #include<cstring> #include<algorithm> usi ...

  9. 51nod 1218 最长递增子序列 | 思维题

    51nod 1218 最长递增子序列 题面 给出一个序列,求哪些元素可能在某条最长上升子序列中,哪些元素一定在所有最长上升子序列中. 题解 YJY大嫂教导我们,如果以一个元素结尾的LIS长度 + 以它 ...

随机推荐

  1. HTML5 Canvas 八星聚义动态效果

    昔有石碣村七星聚义,今有Canvas八星聚义.动态效果是,八颗星以等速螺线慢慢向中心聚集,最后汇聚成一颗. 效果: 代码: <!DOCTYPE html> <html lang=&q ...

  2. HDU 1017 A Mathematical Curiosity (枚举水题)

    Problem Description Given two integers n and m, count the number of pairs of integers (a,b) such tha ...

  3. php中session的理解

    一.Session是什么 Session一般译作会话,牛津词典对其的解释是进行某活动连续的一段时间.从不同的层面看待session,它有着类似但不完全同样的含义.比方,在web应用的用户看来,他打开浏 ...

  4. chm文件打不开的解决办法

    我今天在网上找了找C++函数库,下载下来一个 .chm 文件,打开之后发现只显示了目录,内容却显示不出来. 显示是这样:右边区域显示不出来. 在网上查了一下发现CHM文件是网上比较多的电子书籍显示格式 ...

  5. python 中给文件加锁——fcntl模块

    如果没有fcntl模块则用 sudo pip install fcntl安装 模块简单说明: 打开文件,不存在则创建之 f = open('./test','w') fcntl.flock(f,fcn ...

  6. 最新番茄花园win7系统快速稳定版

    这是最新番茄花园win7系统64位快速稳定版 V2016年2月,该系统由系统妈整理和上传,系统具有更安全.更稳定.更人性化等特点.集成最常用的装机软件,集成最全面的硬件驱动,精心挑选的系统维护工具,加 ...

  7. wpf 获取datagrid 模板列中的控件

    目前采用的 方法  (网上提供的一款) public static DataGridRow GetRow(DataGrid datagrid, int columnIndex)        {    ...

  8. android Bluetooth-蓝牙

    bluetooth 一.开启蓝牙 1.获取BluetoothAdapter BluetoothAdapter.getDefaultAdapter() 2.判断手机设备是否 有蓝牙模块 3.开启蓝牙设备 ...

  9. 基于EasyNVR二次开发实现业务需求:直接集成EasyNVR播放页面到自身项目

    EasyNVR着重点是立足于视频能力层,但是自身也是可以作为一个产品使用的.这就更加方便了应用层的使用. 由于业务需求的缘故,无法使用实体项目展示. 案例描述 该业务系统是国内某大型显示屏生产企业内部 ...

  10. MongoDB在win7上的安装(精简版)

    1.下载mongdb的zip文件,解压后会发现有bin文件夹,在同层目录下建一个data目录, 2.在data目录下建一个log和db文件夹, 3.在log文件下建一个MongoDB.log 文件 4 ...