【模板】LIS模板 洛谷P1091 [NOIP2004提高组]合唱队形 [2017年4月计划 动态规划11]
以题写模板。
写了两个:n^2版本与nlogn版本
P1091 合唱队形
题目描述
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入输出格式
输入格式:
输入文件chorus.in的第一行是一个整数N(2<=N<=100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130<=Ti<=230)是第i位同学的身高(厘米)。
输出格式:
输出文件chorus.out包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
输入输出样例
- 8
- 186 186 150 200 160 130 197 220
- 4
说明
对于50%的数据,保证有n<=20;
对于全部的数据,保证有n<=100。
LIS,即最长上升子序列。
n^2算法:
状态:f[i]表示前i个数(包含第i个)最长上升子序列长度
转移方程:f[i] = max(f[j]),其中1 <= j < i
初始状态:f[i] = 1,其中1 <= i <= n
这个题目很显然正着一遍上升,倒着一遍上升。
正确解法:把所有的点扫一遍,结果为 人数 - (同一个点的正着上升与倒着上升之和减去1(因为加了两次当前这个点)) 的最小值。
错误解法:把所有的点扫一遍,结果为 人数 - (第i个人正着上升与第i+1倒着上升之和))最小值 因为倘若num[i] > num[i+1],可能第i -1个人正着上升与第i个人倒着上升之和才是正解
反例数据(洛谷上的一组):
100
225 176 227 185 171 188 204 152 144 210 190 188 140 150 213 178 177 188 217 154 178 226 217 181 171 206 130 165 135 205 142 180 228 160 179 230 208 196 217 225 180 204 137 149 139 158 133 169 168 145 175 161 154 230 222 210 174 130 186 207 169 192 193 194 223 138 136 173 207 180 218 201 183 190 218 176 149 191 156 206 140 213 151 179 219 202 149 182 148 156 156 179 142 212 135 133 183 201 219
(有耐心的同学自己看吧。。反正我知道放了也是白放。。
nlogn的算法:
f[i]表示最长公共子序列长度为i的子序列末尾数的最小值,初始为正无穷大(0x3f3f3f3f)
可知f[i]一定是单调的
对于num[i],只需要在f中找出大于他的数中最小的,替换掉,替换的这个数的下标就是第i个数的最长公共子序列长度。
手动模拟效果更佳。
n^2版本:
- #include <iostream>
- #include <cstdio>
- #include <cstdlib>
- #include <algorithm>
- #include <cstring>
- #include <vector>
- #define max(a,b) ((a) > (b) ? (a) : (b))
- #define min(a,b) ((a) < (b) ? (a) : (b))
- const int INF = 999999999;
- const int MAXN = 100 + 10;
- inline int read()
- {
- int x = 0;char ch = getchar();char c = ch;
- while(ch > '9' || ch < '0')c = ch,ch = getchar();
- while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0',ch = getchar();
- if(c == '-')return -1 * x;
- return x;
- }
- int lis[MAXN],lds[MAXN],num[MAXN],n,ans,len;
- int main()
- {
- n = read();
- for(int i = 1;i <= n;i ++)
- {
- num[i] = read();
- }
- for(int i = 1;i <= n;i ++)
- {
- lis[i] = 1;
- for(int j = 1;j <= i - 1;j ++)
- {
- if(num[j] < num[i])lis[i] = max(lis[i], lis[j] + 1);
- }
- }
- for(int i = n;i >= 1;i --)
- {
- lds[i] = 1;
- for(int j = n;j >= i + 1;j --)
- {
- if(num[j] < num[i])lds[i] = max(lds[i], lds[j] + 1);
- }
- }
- ans = INF;
- for(int i = 1;i <= n;i ++)
- {
- ans = min(ans, n - lis[i] - lds[i]);
- }
- printf("%d", ans);
- return 0;
- }
nlogn版本:
- #include <iostream>
- #include <cstdio>
- #include <cstdlib>
- #include <algorithm>
- #include <cstring>
- #include <vector>
- #define max(a,b) ((a) > (b) ? (a) : (b))
- #define min(a,b) ((a) < (b) ? (a) : (b))
- const int INF = 999999999;
- const int MAXN = 100 + 10;
- inline int read()
- {
- int x = 0;char ch = getchar();char c = ch;
- while(ch > '9' || ch < '0')c = ch,ch = getchar();
- while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0',ch = getchar();
- if(c == '-')return -1 * x;
- return x;
- }
- int lis[MAXN],lds[MAXN],f[MAXN],num[MAXN],n,ans,len;
- int main()
- {
- n = read();
- for(int i = 1;i <= n;i ++)
- {
- num[i] = read();
- }
- memset(f, 0x3f, sizeof(f));
- f[1] = num[1];lis[1] = 1;
- for(int i = 2;i <= n;i ++)
- {
- f[lis[i] = std::lower_bound(f + 1, f + 1 + n, num[i]) - f] = num[i];
- }
- memset(f, 0x3f, sizeof(f));
- f[1] = num[n];lds[n] = 1;
- for(int i = n - 1;i >= 1;i --)
- {
- int temp = std::lower_bound(f + 1,f + 1 + n, num[i]) - f;
- lds[i] = temp;
- f[temp] = num[i];
- }
- ans = INF;
- for(int i = 1;i <= n ;i ++)
- {
- ans = min(ans, n - lis[i] - lds[i] + 1);
- }
- printf("%d", ans);
- return 0;
- }
【模板】LIS模板 洛谷P1091 [NOIP2004提高组]合唱队形 [2017年4月计划 动态规划11]的更多相关文章
- 洛谷P1091 [NOIP2004 提高组] 合唱队形
本题是一个简单的 LIS(最长上升子序列)问题 只是要求俩次最长上子序列而已 很容易的 首先由于是最长上升子序列 所以朴素法的动态规划表达式为 f[i] = max( f[i] , f[ ...
- P1091 [NOIP2004 提高组] 合唱队形
题目描述 $N$位同学站成一排,音乐老师要请其中的$\left ( N-K\right )$位同学出列,使得剩下的$K$位同学排成合唱队形. 合唱队形是指这样的一种队形:设$K$位同学从左到右依次编号 ...
- 洛谷P1508 Likecloud-吃、吃、吃 [2017年4月计划 动态规划10]
P1508 Likecloud-吃.吃.吃 题目背景 问世间,青春期为何物? 答曰:“甲亢,甲亢,再甲亢:挨饿,挨饿,再挨饿!” 题目描述 正处在某一特定时期之中的李大水牛由于消化系统比较发达,最近一 ...
- 【模板】Tarjan缩点,强连通分量 洛谷P2341 [HAOI2006]受欢迎的牛 [2017年6月计划 强连通分量01]
P2341 [HAOI2006]受欢迎的牛 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的.奶牛之间的“喜欢”是可以传递的 ...
- 洛谷P6033 [NOIP2004 提高组] 合并果子 加强版 (单调队列)
数据加强了,原来nlogn的复杂度就不行了...... 首先对原来的n个数排序(注意不能用快排),因为值域是1e5,所以可以开桶排序,开两个队列,一个存原来的n个数(已经满足单增),另一队列存两两合并 ...
- 洛谷P1368 均分纸牌(加强版) [2017年6月计划 数论14]
P1368 均分纸牌(加强版) 题目描述 有 N 堆纸牌,编号分别为 1,2,…, N.每堆上有若干张,纸牌总数必为 N 的倍数.可以在任一堆上取1张纸牌,然后移动. 移牌规则为:在编号为 1 堆上取 ...
- 洛谷P2912 [USACO08OCT]牧场散步Pasture Walking [2017年7月计划 树上问题 01]
P2912 [USACO08OCT]牧场散步Pasture Walking 题目描述 The N cows (2 <= N <= 1,000) conveniently numbered ...
- 洛谷P1029 最大公约数和最小公倍数问题 [2017年6月计划 数论02]
P1029 最大公约数和最小公倍数问题 题目描述 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数 条件: 1 ...
- 洛谷P1514 [NOIP2010提高组T4]引水入城
P1514 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城 ...
随机推荐
- 19-11-08-Night
再咕咕咕会被爆捶吗??? ZJ: 喜闻乐见: 27 Miemeng 60 01:59:43 100 01:59:44 0 01:59:44 160 01:59:44 最水的$T1$挂了???? $T2 ...
- 力扣算法题—146LRU缓存机制
[题目] 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 (k ...
- eclipse memory analyzer对系统内存溢出堆文件解析0(转)
前言 在平时工作过程中,有时会遇到OutOfMemoryError,我们知道遇到Error一般表明程序存在着严重问题,可能是灾难性的.所以找出是什么原因造成OutOfMemoryError非常重要.现 ...
- <每日一题>题目23:桶排序
''' 桶排序:最快最简单的排序 缺点:最占内存 类型:分布式排序 ''' import cProfile import random def bucketSort(nums): #选出最大的数 ma ...
- java最常用的几种加密算法
1. BASE64 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045-RFC2049,上面有MIME的详细规范.Base64编码可用于在HTTP环境下传递 ...
- HBase Ambari
- 深度学习(二十六)Network In Network学习笔记
深度学习(二十六)Network In Network学习笔记 Network In Network学习笔记 原文地址:http://blog.csdn.net/hjimce/article/deta ...
- 8种nosql数据库对比
1. CouchDB 所用语言: Erlang 特点:DB一致性,易于使用 使用许可: Apache 协议: HTTP/REST 双向数据复制, 持续进行或临时处理, 处理时带冲突检查, 因此,采用的 ...
- mac上开启22号端口
在苹果maC系统SSH 远程登录服务器,采用默认22端口,登录出现了以下的提示: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ...
- python 日记 day3
数据类型的概况:1.int 用于计算. 2.str 用于存储少量数据. 3.list 用于存储大量数据. 4.元祖 又叫只读列表,元素不可更改. 5. dic 用于存储关系型对象 . 6.集合 A.i ...