51nod 1376 最长递增子序列的数量(dp、CDQ分治 | BIT)
题意:
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)相关推荐
- [51Nod 1218] 最长递增子序列 V2 (LIS)
传送门 Description 数组A包含N个整数.设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可 ...
- 51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最 ...
- [51nod1376] 最长递增子序列的数量
51nod1376 #include<bits/stdc++.h> using namespace std; const int N = 5e4+10, mod = 1000000007; ...
- leetcode - 673. 最长递增子序列的个数
给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7] ...
- 动态规划(最长递增子序列)---最长递增子序列
最长递增子序列 300. Longest Increasing Subsequence (Medium) 题目描述: 给定一个数组,找到它的最长递增子序列 思路分析: 动态规划思想,定义一个数 ...
- 最长递增子序列(力扣)图解
最长递增子序列(力扣) 原题 题目描述 解题思路 代码 图解 原题 题目链接 题目描述 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列 是由数组派生而来的序列,删除(或不删除 ...
- 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串 (转)...
作者:寒小阳 时间:2013年9月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/11969497. 声明:版权所有,转载请注明出处,谢谢 ...
- 动态规划算法 | 最长递增子序列
通过查阅相关资料发现动态规划问题一般就是求解最值问题.这种方法在解决一些问题时应用比较多,比如求最长递增子序列等. 有部分人认为动态规划的核心就是:穷举.因为要求最值,肯定要把所有可行的答案穷举出来, ...
- 耐心排序之最长递增子序列(LIS)
目录 一.问题引入 1.最长递增子序列(LIS) 2.问题分析 3.代码实现 4.问题思考 二.耐心排序 1.基本介绍 2.操作步骤 3.代码实现 三.俄罗斯套娃信封问题 1.题目描述 2.问题分析 ...
最新文章
- [笔记]C#基础入门(八)——C#标识符的命名规则
- 高考623分却说自己是“反面教材”?外卖小哥最新发声!
- windows下db2数据库的卸载
- yum安装mysql驱动_centos7下使用yum安装mysql
- 有关调试CRM系统的一些感想
- 【Python基础】Python中必须知道的5对魔术方法
- Oracle入门(十四.7)之良好的编程习惯
- 内存不足:杀死进程或牺牲孩子
- Shell文件读取方法集锦
- 软件测试从业 3 年+了,怎么兼顾 管理 与 自身成长?
- php 编辑器格式输出_高效PHP开发人员的十大PHP开发工具
- 0x7c97cd12 指令引用的 0x00000014内存。该内存不能为written
- C 语言调用python 脚本函数
- Excel中将汉字(名字)转换为拼音
- 正确认识使用Word模板
- 中国新能源汽车电机及控制器行业需求态势与十四五方向分析报告2021年版
- 校园招聘-2017携程秋招后台开发笔试编程题
- 总结:Springboot的pom配置
- 手机端微信突然弹出电脑端已登录,是什么原因?
- 教育部高等教育司指定大学生必读100本书目
热门文章
- App inventor arduino 手机蓝牙通信实现
- 【达内课程】面向对象之多态
- 从高维变换的角度理解神经网络
- Python超级素数
- macbook2016款学计算机,捡垃圾之路 篇一:Macbook Pro 2016款,2020年捡垃圾心得。
- 90后“老头儿”和00后Go小子的硬盘夜话
- 程序清单5.3_golf.c程序_《C Primer Plus》P90
- matlab eig eigs,Matlab中的eig函数跟eigs函数的异同点
- Oracle课程知识点总结(2)
- CSS它究竟是什么呢?如何学好CSS呢?