【刷题】BZOJ 3591 最长上升子序列
Description
给出1~n的一个排列的一个最长上升子序列,求原排列可能的种类数。
Input
第一行一个整数n。
第二行一个整数k,表示最长上升子序列的长度。
第三行k个整数,表示这个最长上升子序列。
Output
第一行一个整数,表示原排列可能的种类数。
Sample Input
5
3
1 3 4
Sample Output
11
HINT
【样例说明】
11种排列分别为(1, 3, 2, 5, 4), (1, 3, 5, 2, 4), (1, 3, 5, 4, 2), (1, 5, 3, 2, 4), (1, 5, 3, 4, 2), (2, 1, 3, 5, 4), (2, 1, 5, 3, 4), (2, 5, 1, 3, 4), (5, 1, 3, 2, 4), (5, 1, 3, 4, 2), (5, 2, 1, 3, 4)。
【数据规模和约定】
对于30%的数据,1 <= n <= 11。
对于70%的数据,1 <= n <= 14。
对于100%的数据,1 <= n <= 15,答案小于2^31。
Solution
一道dp题
我们先考虑对一个数列求LIS的方法(\(log\) 的那个),一个 \(lis\) 数组,\(lis[i]\) 记录长度为 \(i\) 的LIS的末尾最小可以是多少
对于 \(lis\) 整个数组,不难发现它是单调递增的,所以我们可以用二进制表示它,一样是01表示某个数是否出现在 \(lis\) 数组中,因为递增,所以我们这要知道有哪些数在里面,就可以还原出原来的 \(lis\) 数组
然后考虑本题的dp,我们用一个 \(f\) ,考虑对于当前的LIS,插入新数的情况
所以要保存每个数的三个状态
一是这个数还没有被考虑,二是这个数已被考虑,并且在LIS数组中出现,三是这个数已经被考虑,并且已经被弹出LIS数组
所以用三进制压位,012分别代表上面三个状态
转移时,枚举每一个LIS的情况,然后枚举每一个数,插入进去,再把当前的状态转移到插入后的状态
这种dp题看代码更好理解
#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
const int MAXN=16,MAXN_3=14348907+10;
int A[MAXN],n,m,pos[MAXN],lis[MAXN],vis[MAXN],val[MAXN],f[MAXN_3],ans,qexp3[MAXN];
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
read(n);read(m);
for(register int i=1;i<=m;++i)
{
read(A[i]);
A[i]--;
pos[A[i]]=i;
if(i>=2&&A[i-1]>A[i])
{
write(0,'\n');
return 0;
}
}
qexp3[0]=1;
for(register int i=1;i<=n;++i)qexp3[i]=qexp3[i-1]*3;
f[0]=1;
for(register int i=0;i<qexp3[n];++i)
{
if(!f[i])continue;
int x=i,lislen=0,app=0;
for(register int j=0;j<n;++j)
{
val[j]=vis[j]=x%3;
x/=3;
if(vis[j])app++;
if(val[j]==1)lis[lislen++]=j;
}
if(app==n)
{
ans+=f[i];
continue;
}
int ins=0;
for(register int j=0;j<n;++j)
{
if(vis[j])continue;
if(pos[j]>1&&!vis[A[pos[j]-1]])continue;
while(ins<lislen&&lis[ins]<j)ins++;
if(ins==m)continue;
int nxt=i+qexp3[j];
if(ins<lislen)nxt+=qexp3[lis[ins]];
f[nxt]+=f[i];
}
}
write(ans,'\n');
return 0;
}
【刷题】BZOJ 3591 最长上升子序列的更多相关文章
- BZOJ.3591.最长上升子序列(状压DP)
BZOJ 题意:给出\(1\sim n\)的一个排列的一个最长上升子序列,求原排列可能的种类数. \(n\leq 15\). \(n\)很小,参照HDU 4352这道题,我们直接把求\(LIS\)时的 ...
- BZOJ 2423 最长公共子序列
Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0, ...
- BZOJ 3173 最长上升子序列(树状数组+二分+线段树)
给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? 由于序列是顺序插入的,所以当前插入的数字对之 ...
- BZOJ 5427: 最长上升子序列
$f[i] 表示长度为i的最长上升子序列的最后一位的最小值是多少$ 对于普通的$LIS我们可以二分确定位置去更新$ 再来考虑对于这个,如果有某一位没有确定的话 那么这一位是可以随便取的,也就是说,所有 ...
- bzoj 3173 最长上升子序列
Written with StackEdit. Description 给定一个序列,初始为空.现在我们将\(1\)到\(N\)的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字, ...
- #leetcode刷题之路32-最长有效括号
给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度. 示例 1:输入: "(()"输出: 2解释: 最长有效括号子串为 "()"示 ...
- #leetcode刷题之路14-最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow" ...
- #leetcode刷题之路5-最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1:输入: "babad"输出: "bab"注意: " ...
- 刷题总结:最长公共字串(spoj1811)(后缀自动机)
题目: 就不贴了吧···如题: 题解: 后缀自动机模版题:没啥好说的···· 代码: #include<iostream> #include<cstdio> #include& ...
随机推荐
- 【TestNG测试】TestNG、Maven、testng.xml构建测试工程
创建一个maven工程 使用Idea创建maven工程 建立类似如上的工程结构,src/main/java,src/test/java,pom.xml,testng.xml,这里由于我们使用工程是 ...
- 使用Chrome控制台进行3D模型编辑的尝试
前言:3D模型编辑的核心是对顶点位置和纹理颜色的编辑,这个研究的目的在于寻找一种通过编程方式直接对模型进行编辑的方法,这种编辑方法和时下流行的通过鼠标点选.拖拽进行编辑的方法之间的关系,和前端编程中“ ...
- 引用“kernel32”读写ini配置文件
引用"kernel32"读写ini配置文件 unity ini kernel32 配置文件 引用"kernel32"读写ini配置文件 OverView ke ...
- Influxdb配置文件详解---influxdb.conf
官方介绍:https://docs.influxdata.com/influxdb/v1.2/administration/config/ 全局配置 1 2 reporting-disabled = ...
- ossec兼容的操作系统
OSSEC兼容以下操作系统和日志格式 操作系统 以下操作系统可安装OSSEC代理 l GNU/Linux (all distributions, including RHEL, Ubuntu, Sl ...
- Go文件右键编译
辛辛苦苦写好了.go文件 发现编译还得敲命令才行,或许配置一个好用点的IDE环境可以解决 但是有时候实在不想开IDE 于是在右键添加了一个编译功能 首先保证go相关的环境变量配置正确 Windows ...
- Refs 和 DOM
在常规的 React 数据流中,props 是父组件与子组件交互的唯一方式.要修改子元素,你需要用新的 props 去重新渲染子元素.然而,在少数情况下,你需要在常规数据流外强制修改子元素.被修改的子 ...
- DB2分页查询简单示例
select * from ( select a.* ,rownumber() over(order by create_time desc) as rowid from ( select * fro ...
- 今日事——Sprint计划会议
一. Sprint需求: 解屏提醒部分 界面设计 登录功能 备忘功能 成就系统 二.工作认领: 因有成员请假回家,所以延后认领,目前主要任务是学习如何在andriod平台开发并搭建开发环境. 网上 ...
- [BUAA_SE_2017]提问回顾
提问回顾 学期初疑问回答 学期初疑问博客 教材中说,PM在衡量需求时需要方方面面的能力与研究.可是,当下许多互联网IT公司只承担外包业务,即客户给什么需求就实现什么需求,甚至可能不要求其它先进的功能. ...