题意:

N≤5×104的序列,0≤Ai≤109,求LIS的数量N\le5\times10^4的序列, 0\le A_i\le 10^9, 求LIS的数量

分析:

f[i]:以第i个数结尾的LIS的长度,和该长度的LIS数量f[i]:以第i个数结尾的LIS的长度, 和 该长度的LIS数量
转移的话,显然f[i].first=max{f[j].first}+1,j<i且a[j]<a[i]转移的话, 显然f[i].first = max\{f[j].first\}+1,j
f[i].second=∑jf[j].second,f[j].first=f[i].first−1f[i].second=\sum_{j}f[j].second,f[j].first=f[i].first-1
我们可以用BIT来优化这个转移,维护≤i的最大长度和对应数量我们可以用BIT来优化这个转移, 维护\le i的最大长度和对应数量

代码:

//
//  Created by TaoSama on 2016-02-16
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;int n, a[N];using P = pair<int, int>;void getMax(P& x, P y) {if(x.first < y.first) x = y;else if(x.first == y.first) {if((x.second += y.second) >= MOD)x.second -= MOD;}
}struct BIT {int n; P b[N];void init(int _n) {n = _n;for(int i = 1; i <= n; ++i) b[i] = P(0, 0);}void add(int i, P v) {for(; i <= n; i += i & -i) getMax(b[i], v);}P sum(int i) {P ret(0, 1);for(; i; i -= i & -i) getMax(ret, b[i]);return ret;}
} bit;int main() {
#ifdef LOCALfreopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endifios_base::sync_with_stdio(0);scanf("%d", &n);vector<int> xs;for(int i = 1; i <= n; ++i) {scanf("%d", a + i);xs.push_back(a[i]);}sort(xs.begin(), xs.end());xs.resize(unique(xs.begin(), xs.end()) - xs.begin());bit.init(xs.size());P ans(0, 0);for(int i = 1; i <= n; ++i) {int x = lower_bound(xs.begin(), xs.end(), a[i]) - xs.begin() + 1;P cur = bit.sum(x - 1);++cur.first;getMax(ans, cur);bit.add(x, cur);}printf("%d\n", ans.second);return 0;
}

当然其实这是个二维偏序问题,一维下标,二维值当然其实这是个二维偏序问题, 一维下标, 二维值
直接cdq分治做就可以了,复杂度多一个log,是O(nlog2n)直接cdq分治做就可以了, 复杂度多一个log, 是O(nlog^2n)
为了避开相等有个小技巧,间隔排序很机智,把可能成为询问的排到了第一个,从知乎学到的@李贝瑀为了避开相等有个小技巧, 间隔排序很机智, 把可能成为询问的排到了第一个, 从知乎学到的@李贝瑀

代码:

//
//  Created by TaoSama on 2016-02-16
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;int n, a[N];using P = pair<int, int>;P f[N]; //LIS length, countvoid getMax(P& x, P y) {if(x.first < y.first) x = y;else if(x.first == y.first) {if((x.second += y.second) >= MOD)x.second -= MOD;}
}int id[N];
bool cmp(int x, int y) {if(a[x] != a[y]) return a[x] < a[y];return x > y;
}void cdq(int l, int r) {if(l == r) return;int m = l + r >> 1;cdq(l, m);for(int i = l; i <= r; ++i) id[i] = i;sort(id + l, id + r + 1, cmp);P maxf(0, 0);for(int i = l; i <= r; ++i) {int idx = id[i];if(idx <= m) getMax(maxf, f[idx]);else {P cur = maxf;++cur.first;getMax(f[idx], cur);}}cdq(m + 1, r);
}int main() {
#ifdef LOCALfreopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endifios_base::sync_with_stdio(0);scanf("%d", &n);for(int i = 1; i <= n; ++i) scanf("%d", a + i);for(int i = 1; i <= n; ++i) f[i] = P(1, 1);cdq(1, n);P ans(0, 0);for(int i = 1; i <= n; ++i) getMax(ans, f[i]);printf("%d\n", ans.second);return 0;
}

51nod 1376 最长递增子序列的数量(dp、CDQ分治 | BIT)相关推荐

  1. [51Nod 1218] 最长递增子序列 V2 (LIS)

    传送门 Description 数组A包含N个整数.设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可 ...

  2. 51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子

    给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最 ...

  3. [51nod1376] 最长递增子序列的数量

    51nod1376 #include<bits/stdc++.h> using namespace std; const int N = 5e4+10, mod = 1000000007; ...

  4. leetcode - 673. 最长递增子序列的个数

    给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7] ...

  5. 动态规划(最长递增子序列)---最长递增子序列

    最长递增子序列 300. Longest Increasing Subsequence (Medium) 题目描述:   给定一个数组,找到它的最长递增子序列 思路分析:   动态规划思想,定义一个数 ...

  6. 最长递增子序列(力扣)图解

    最长递增子序列(力扣) 原题 题目描述 解题思路 代码 图解 原题 题目链接 题目描述 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列 是由数组派生而来的序列,删除(或不删除 ...

  7. 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串 (转)...

    作者:寒小阳 时间:2013年9月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/11969497. 声明:版权所有,转载请注明出处,谢谢 ...

  8. 动态规划算法 | 最长递增子序列

    通过查阅相关资料发现动态规划问题一般就是求解最值问题.这种方法在解决一些问题时应用比较多,比如求最长递增子序列等. 有部分人认为动态规划的核心就是:穷举.因为要求最值,肯定要把所有可行的答案穷举出来, ...

  9. 耐心排序之最长递增子序列(LIS)

    目录 一.问题引入 1.最长递增子序列(LIS) 2.问题分析 3.代码实现 4.问题思考 二.耐心排序 1.基本介绍 2.操作步骤 3.代码实现 三.俄罗斯套娃信封问题 1.题目描述 2.问题分析 ...

最新文章

  1. [笔记]C#基础入门(八)——C#标识符的命名规则
  2. 高考623分却说自己是“反面教材”?外卖小哥最新发声!
  3. windows下db2数据库的卸载
  4. yum安装mysql驱动_centos7下使用yum安装mysql
  5. 有关调试CRM系统的一些感想
  6. 【Python基础】Python中必须知道的5对魔术方法
  7. Oracle入门(十四.7)之良好的编程习惯
  8. 内存不足:杀死进程或牺牲孩子
  9. Shell文件读取方法集锦
  10. 软件测试从业 3 年+了,怎么兼顾 管理 与 自身成长?
  11. php 编辑器格式输出_高效PHP开发人员的十大PHP开发工具
  12. 0x7c97cd12 指令引用的 0x00000014内存。该内存不能为written
  13. C 语言调用python 脚本函数
  14. Excel中将汉字(名字)转换为拼音
  15. 正确认识使用Word模板
  16. 中国新能源汽车电机及控制器行业需求态势与十四五方向分析报告2021年版
  17. 校园招聘-2017携程秋招后台开发笔试编程题
  18. 总结:Springboot的pom配置
  19. 手机端微信突然弹出电脑端已登录,是什么原因?
  20. 教育部高等教育司指定大学生必读100本书目

热门文章

  1. App inventor arduino 手机蓝牙通信实现
  2. 【达内课程】面向对象之多态
  3. 从高维变换的角度理解神经网络
  4. Python超级素数
  5. macbook2016款学计算机,捡垃圾之路 篇一:Macbook Pro 2016款,2020年捡垃圾心得。
  6. 90后“老头儿”和00后Go小子的硬盘夜话
  7. 程序清单5.3_golf.c程序_《C Primer Plus》P90
  8. matlab eig eigs,Matlab中的eig函数跟eigs函数的异同点
  9. Oracle课程知识点总结(2)
  10. CSS它究竟是什么呢?如何学好CSS呢?