51Nod 1376 最长递增子序列的数量 (DP+BIT)
题意:略。
析:dp[i] 表示以第 i 个数结尾的LIS的长度和数量,状态方程很好转移,先说长度 dp[i] = max { dp[j] + 1 | a[i] > a[j] && j < i },然后是数量,dp[i] = sigma(dp[j]) if dp[i] == dp[j] + 1。
如果普通转移时间复杂度很高,达不到要求,由于有个求和的操作,可以考虑用BIT优化,先把每个数离散化,然后对每个数只要求小于它的数,并且长度最长的就好了,数量也是,如果长度一样就进行合并,否则不合并,或者更新长度。
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#include <numeric>
#define debug() puts("++++")
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(i,x,n) for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e17;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 5e4 + 10;
const int maxm = 1e6 + 5;
const int mod = 1000000007;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, -1, 0, 1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
return r >= 0 && r < n && c >= 0 && c < m;
} void update(P &a, P b){
if(a.fi < b.fi) a = b;
else if(a.fi == b.fi){
a.se += b.se;
if(a.se >= mod) a.se -= mod;
}
} P sum[maxn]; inline int lowbit(int x){ return -x&x; } void add(int x, P c){
while(x <= m){
update(sum[x], c);
x += lowbit(x);
}
} P query(int x){
P ans(0, 1);
while(x){
update(ans, sum[x]);
x -= lowbit(x);
}
return ans;
}
int a[maxn];
vector<int> v; int getpos(int x){ return lower_bound(v.begin(), v.end(), x) - v.begin() + 1; } int main(){
scanf("%d", &n);
v.resize(n);
for(int i = 0; i < n; ++i){
scanf("%d", a+i);
v[i] = a[i];
}
sort(v.begin(), v.end());
v.resize(unique(v.begin(), v.end()) - v.begin());
m = v.sz;
P ans(0, 1);
for(int i = 0; i < n; ++i){
int pos = getpos(a[i]);
P tmp = query(pos - 1);
++tmp.fi;
update(ans, tmp);
add(pos, tmp);
}
printf("%d\n", ans.se);
return 0;
}
分治:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#include <numeric>
#define debug() puts("++++")
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(i,x,n) for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e17;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 5e4 + 10;
const int maxm = 1e6 + 5;
const int mod = 1000000007;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, -1, 0, 1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
return r >= 0 && r < n && c >= 0 && c < m;
} void update(P &a, P b){
if(a.fi < b.fi) a = b;
else if(a.fi == b.fi){
a.se += b.se;
if(a.se >= mod) a.se -= mod;
}
}
P dp[maxn], res; int id[maxn], a[maxn]; inline bool cmp(int x, int y){ return a[x] == a[y] ? x > y : a[x] < a[y]; } void dfs(int l, int r){
if(l == r){ update(dp[l], P(1, 1)); return ; }
int m = l + r >> 1;
dfs(l, m);
for(int i = l; i <= r; ++i) id[i] = i;
sort(id+l, id+r+1, cmp); P ans = P(0, 0);
for(int i = l; i <= r; ++i){
int idx = id[i];
if(idx <= m) update(ans, dp[idx]);
else{
P tmp = ans;
++tmp.fi;
update(dp[idx], tmp);
update(res, tmp);
}
}
dfs(m+1, r);
} int main(){
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%d", a+i);
dfs(0, n-1);
printf("%d\n", res.se);
return 0;
}
51Nod 1376 最长递增子序列的数量 (DP+BIT)的更多相关文章
- 51nod 1376 最长递增子序列的数量(线段树)
51nod 1376 最长递增子序列的数量 数组A包含N个整数(可能包含相同的值).设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递 ...
- 51Nod 1376 最长递增子序列的数量 —— LIS、线段树
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376 1376 最长递增子序列的数量 基准时间限制:1 秒 空 ...
- 51NOD 1376 最长递增子序列的数量 [CDQ分治]
1376 最长递增子序列的数量 首先可以用线段树优化$DP$做,转移时取$0...a[i]$的最大$f$值 但我要练习$CDQ$ $LIS$是二维偏序问题,偏序关系是$i<j,\ a_i< ...
- 51nod 1376 最长上升子序列的数量 | DP | vector怒刷存在感!
51nod 1376 最长上升子序列的数量 题解 我们设lis[i]为以位置i结尾的最长上升子序列长度,dp[i]为以位置i结尾的最长上升子序列数量. 显然,dp[i]要从前面的一些位置(设为位置j) ...
- 51nod 1376 最长递增子序列的数量(不是dp哦,线段树 + 思维)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376 题解:显然这题暴力的方法很容易想到就是以每个数为结尾最 ...
- 【51nod】1376 最长递增子序列的数量
数组A包含N个整数(可能包含相同的值).设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可能有很多个. ...
- 51nod 1218 最长递增子序列 V2(dp + 思维)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1218 题解:先要确定这些点是不是属于最长递增序列然后再确定这 ...
- 51nod1376 最长递增子序列的数量
O(n2)显然超时.网上找的题解都是用奇怪的姿势写看不懂TAT.然后自己YY.要求a[i]之前最大的是多少且最大的有多少个.那么线段树维护两个值,一个是当前区间的最大值一个是当前区间最大值的数量那么我 ...
- 51nod 1134 最长递增子序列
题目链接:51nod 1134 最长递增子序列 #include<cstdio> #include<cstring> #include<algorithm> usi ...
随机推荐
- WP runtime post 请求, json 解析
https://monkeyweekend.wordpress.com/2014/10/23/how-to-send-text-json-or-files-using-httpclient-posta ...
- JAVA发送HttpClient请求及接收请求结果过程
1.写一个HttpRequestUtils工具类,包括post请求和get请求 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ...
- ubuntu ftp 建立匿名用户 [转]
转自:http://www.cnblogs.com/cocoajin/p/3761414.html ubuntu server vsftpd 匿名用户上传下载及目录设置 1:vsftpd服务器安装: ...
- js函数中变量声明提前
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- Null Hypothesis and Alternate Hypothesis
1.Null Hypothesis Overview 零假设,H0是普遍接受的事实;这与备择假设(alternate hypothesis)正好相反.研究人员努力否定.驳斥零假设.研究人员提出了另一种 ...
- Java RSA 生成公钥 私钥
目前为止,RSA是应用最多的公钥加密算法,能够抵抗已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准. RSA算法中,每个通信主体都有两个钥匙,一个公钥(Public Key)用来对数据进行加密 ...
- sqldatareader无法得到output参数的解决
只需要在所有的sqldatareader结束后,加上一句就可以得到输出参数了. sdr.Close(); Object ObjCount = cmd.Parameters["@Count_P ...
- python,遍历文件的方法
在做验证码识别时,识别时需要和库里的图片对比,找到最接近的那个图片,然后就行到了用与图片一致的字符命名,获取文件的名称,去将图片的名称读出来作为验证码.以下是我通过网上的资料总结的三种文件遍历的方式, ...
- wireshark使用相关问题
问题1: 打开wireshark,没有出现过滤器 解决1: 使用管理员方式登录 过滤: http and ip.src == 192.168.0.10 and ip.dst == 192.168.0. ...
- 从RTTI谈C++的向下转型
转自:http://blog.chinaunix.net/uid-28541347-id-4251713.html 从RTTI谈C++的向下转型 1.什么是RTTI? RTTI 是“Runtime T ...