[codeforces743E]Vladik and cards
2 seconds
256 megabytes
standard output
Vladik was bored on his way home and decided to play the following game. He took n cards and put them in a row in front of himself. Every card has a positive integer number not exceeding 8 written on it. He decided to find the longest subsequence of cards which satisfies the following conditions:
- the number of occurrences of each number from 1 to 8 in the subsequence doesn't differ by more then 1 from the number of occurrences of any other number. Formally, if there are ck cards with number k on them in the subsequence, than for all pairs of integers the condition |ci - cj| ≤ 1 must hold.
- if there is at least one card with number x on it in the subsequence, then all cards with number x in this subsequence must form a continuous segment in it (but not necessarily a continuous segment in the original sequence). For example, the subsequence [1, 1, 2, 2] satisfies this condition while the subsequence [1, 2, 2, 1] doesn't. Note that [1, 1, 2, 2] doesn't satisfy the first condition.
Please help Vladik to find the length of the longest subsequence that satisfies both conditions.
The first line contains single integer n (1 ≤ n ≤ 1000) — the number of cards in Vladik's sequence.
The second line contains the sequence of n positive integers not exceeding 8 — the description of Vladik's sequence.
Print single integer — the length of the longest subsequence of Vladik's sequence that satisfies both conditions.
3
1 1 1
1
8
8 7 6 5 4 3 2 1
8
24
1 8 1 2 8 2 3 8 3 4 8 4 5 8 5 6 8 6 7 8 7 8 8 8
17
In the first sample all the numbers written on the cards are equal, so you can't take more than one card, otherwise you'll violate the first condition.
题解:
先简单翻译一下,给一个序列,求最长的满足下面条件的子序列:
第一,相同数字连续;第二,每种数字出现次数之差不超过1
我们来考虑,由于每种数字出现都是连续的,因此一种数字一旦出现过,就不能再出现第二次。
所以我们可以用二进制来压每种数字是否出现过。
那么,每种数字出现次数的限制怎么处理?
这个东西不好说,所以我们考虑,如果有一种选择,使得每种数字都出现了至少a次,
那么一定会有其他选择,使得每种数字都出现了至少a-1次,a-2次……1次。
因此,我们就可以二分了!二分枚举每种数字至少出现的次数len,那么每种数字要么出现len次,要么出现len+1次。
对于某个len,定义状态数组f[i][j]为前i位中,数字出现状态为j时出现len+1次的数的最大种数
设tmp=max{f[i][(1<<8)-1}},那么显然,ans=tmp*(len+1)+(8-tmp)*len
在选取新的数字时,新数字要么出现len次,要么出现len+1次,
那么状态方程也显而易见了(刷表),更新对应位置的f值即可
最后注意特判:如果二分得到len=0,那么ans=出现的数的种数
代码见下:
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N=;
const int K=(<<)+;
int n,a[N],f[N][K],now[],bit[];//now数组用来记录转移位置
inline int max(int a,int b){return a>b?a:b;}
vector<int> loc[];
inline int judge(int len)
{
for(int i=;i<=;i++)now[i]=;
memset(f,0xaf,sizeof(f));
int inf=f[][];
f[][]=;
for(int i=;i<n;i++)
{
for(int j=;j<bit[];j++)
{
if(f[i][j]==inf)continue;
for(int k=;k<;k++)
{
if(j&bit[k])continue;
int pos=now[k+]+len-;
if(pos>=loc[k+].size())continue;
f[loc[k+][pos]][j|bit[k]]=max(f[loc[k+][pos]][j|bit[k]],f[i][j]);
pos++;
if(pos>=loc[k+].size())continue;
f[loc[k+][pos]][j|bit[k]]=max(f[loc[k+][pos]][j|bit[k]],f[i][j]+);
}
}
now[a[i]]++;
}
int ans=inf;
for(int i=;i<=n;i++)
ans=max(ans,f[i][bit[]-]);
if(ans==inf)return -;
return ans*(len+)+(-ans)*len;
}
int main()
{
bit[]=;for(int i=;i<=;i++)bit[i]=bit[i-]<<;
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&a[i]),loc[a[i]].push_back(i);
int l=,r=n/+,ans=;
while(l<=r)
{
int mi=(l+r)>>;
if(judge(mi)!=-)ans=judge(mi),l=mi+;
else r=mi-;
}
if(ans==)
{
ans=;
for(int i=;i<=;i++)
if(!loc[i].empty())ans++;
}
printf("%d",ans);
}
codeforces743E
[codeforces743E]Vladik and cards的更多相关文章
- CodeForces743E. Vladik and cards 二分+状压dp
这个题我们可以想象成_---___-----__的一个水柱它具有一遍优一遍行的性质因此可以用来二分最小值len,而每次二分后我们都要验根,we可以把这个水柱想成我们在每个数段里取前一段的那个数后一段有 ...
- Codeforces Round #384 (Div. 2) 734E Vladik and cards
E. Vladik and cards time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- Codeforces Round #384 (Div. 2) E. Vladik and cards 状压dp
E. Vladik and cards 题目链接 http://codeforces.com/contest/743/problem/E 题面 Vladik was bored on his way ...
- Vladik and cards
Vladik and cards time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- CF384 div2 E. Vladik and cards
题意 给你一个的排列,求一个满足条件的最长子序列 每种数字的差小于等于,并且每种数字之内是连续的 解法 首先单纯认为用肯定不行的 所以应该考虑二分答案(所求长度具有二分性) 再用dp判断是否可行,这个 ...
- Vladik and cards CodeForces - 743E (状压)
大意: 给定序列, 求选出一个最长的子序列, 使得任选两个[1,8]的数字, 在子序列中的出现次数差不超过1, 且子序列中相同数字连续. 正解是状压dp, 先二分转为判断[1,8]出现次数>=x ...
- 【codeforces 743E】Vladik and cards
[题目链接]:http://codeforces.com/problemset/problem/743/E [题意] 给你n个数字; 这些数字都是1到8范围内的整数; 然后让你从中选出一个最长的子列; ...
- Codeforces Round #384 (Div. 2) //复习状压... 罚时爆炸 BOOM _DONE
不想欠题了..... 多打打CF才知道自己智商不足啊... A. Vladik and flights 给你一个01串 相同之间随便飞 没有费用 不同的飞需要费用为 abs i-j 真是题意杀啊, ...
- 「算法笔记」状压 DP
一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...
随机推荐
- 解决 idea template jsp模板中使用自定义路径 模板不显示问题
${} 是一个模板中的关键字,所以建立时需要用 \ 注释即可正常显示 ${APP_PATH}
- javaweb(十五)——JSP基础语法
任何语言都有自己的语法,JAVA中有,JSP虽然是在JAVA上的一种应用,但是依然有其自己扩充的语法,而且在JSP中,所有的JAVA语句都可以使用. 一.JSP模版元素 JSP页面中的HTML内容称之 ...
- Wince 中访问WCF服务
由于本文并非WinCE开发普及篇,所以一些WinCE开发和WCF开发的基础还请移步百度和谷歌寻找答案,然后结合本文开发出WinCE中如何访问WCF,谢谢. 开发环境 IDE:Visual Studio ...
- 怎样安装Scrapy
Windows怎样安装Scrapy? pip install scrapy会报错 访问https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 下载并放到 ...
- MySQL事务、并发问题、锁机制
MySQL事务,并发问题,锁机制 1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库 ...
- “错误: 编码GBK的不可映射字符” 的解决方案
命令行下,用javac命令编译java程序时,如果文档的编码为“utf-8”,并且含有中文字符时,会出现乱码现象,编译通过不了.如图: 解决方案:编译时指定编码方式,防止乱码.如下:
- JavaScript事件冒泡和捕获
事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件. 事件冒泡是自下而上的去触发事件. 绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获.true,事件捕获:fa ...
- 数据库MySql在python中的使用
随着需要存储数据的结构不断复杂化,使用数据库来存储数据是一个必须面临的问题.那么应该如何在python中使用数据库?下面就在本篇博客中介绍一下在python中使用mysql. 首先,本博客已经假定阅读 ...
- netty初认识
Netty是什么? 本质:JBoss做的一个Jar包 目的:快速开发高性能.高可靠性的网络服务器和客户端程序 优点:提供异步的.事件驱动的网络应用程序框架和工具 通俗的说:一个好使的处理Socket的 ...
- 详讲H5、WebApp项目中常见的坑以及注意事项
首先我们中会有一些常用的meta标签,如下: <!--防止手机中网页放大和缩小--> <meta name="viewport" content="wi ...