题目链接: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. windows8开发-关于wp7应用迁移到win8 metro风格

    虽然微软说,wp7应用移植到win8上面是比较简单,只需要修改部分API和设计原则上的细节,同时它也提供了一份比较简洁的参考文档: 而实际上这种移植的工作量还是不小的,尤其当应用引用了较多底层的API ...

  2. 2017.3.27 集成modeler后的一些主要路径(持续更新)

    1.设计器访问路径 项目名:wfs_web edtor-app和modeler.html的存放位置:webapp/designer/editor-app app-cfg.js中根路径设置:'conte ...

  3. AngularJS中,<span class="bluetext" ng-bind="ctrl.user.name|uppercase"></span>和{{ctrl.user.name|uppercase}}是等价的,但不等于<span class="bluetext" ng-bind="ctrl.user.name|uppercase"/>

    代码下载:https://files.cnblogs.com/files/xiandedanteng/angularjsAttenSpan.rar AngularJS中,<span class= ...

  4. 我是如何通过一个 XSS 探测搜狐内网扫描内网并且蠕动前台到最后被发现的

    我是如何通过一个 XSS 探测搜狐内网扫描内网并且蠕动前台到最后被发现的!(附带各种 POC) | WooYun-2014-76685 | WooYun.orghttp://wooyun.org/bu ...

  5. LeetCode Recover Binary Search Tree——二查搜索树中两个节点错误

    Two elements of a binary search tree (BST) are swapped by mistake.Recover the tree without changing ...

  6. Nexus 5刷阿里云OS

    刷机有风险,刷机需慎重! 1. 下载 recovery 的img和 阿里云os. recovery 的img下载: https://kanbox.com/f/V00KA 阿里云OS3.0.3 : 2月 ...

  7. Shell脚本之:替换

    转义字符 #!/bin/bash a= echo -e "Value of a is $a \n" 使用-e表示对转义字符进行替换,默认情况是不转义的 命令替换 命令替换的语法,注 ...

  8. 统一建模语言(UML,Unified Modeling Language)

    Something about UML: 统一建模语言(UML,英语:Unified Modeling Language)是非专利的第三代建模和规约语言.UML是一种开放的方法,用于说明.可视化.构建 ...

  9. web前端的一些实用技能

    如今我们使用的互联网,客户端与服务器端的交互无时无刻不在发生.比如我们在浏览器打开网页,浏览器就是客户端,将网页数据发过来的也就是服务器.其实服务器,并没有什么特别的,也就是一台昼夜不停运转的电脑罢了 ...

  10. Realm多线程中的那些坑...

    个人在开发中遇到的一些小坑... 可能会持续更新... 1.RealmObject自带线程保护功能.仅仅能在创建它的线程中訪问.在子线程中不能訪问. 也就是说.假设你在主线程中new了一个RealmO ...