E. Vladik and cards
time limit per test 

2 seconds

memory limit per test 

256 megabytes

input standard input

output 

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.

Input

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.

Output

Print single integer — the length of the longest subsequence of Vladik's sequence that satisfies both conditions.

Examples
input
3
1 1 1
output
1
input
8
8 7 6 5 4 3 2 1
output
8
input
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
output
17
Note

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的更多相关文章

  1. CodeForces743E. Vladik and cards 二分+状压dp

    这个题我们可以想象成_---___-----__的一个水柱它具有一遍优一遍行的性质因此可以用来二分最小值len,而每次二分后我们都要验根,we可以把这个水柱想成我们在每个数段里取前一段的那个数后一段有 ...

  2. 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 ...

  3. 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 ...

  4. Vladik and cards

    Vladik and cards time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  5. CF384 div2 E. Vladik and cards

    题意 给你一个的排列,求一个满足条件的最长子序列 每种数字的差小于等于,并且每种数字之内是连续的 解法 首先单纯认为用肯定不行的 所以应该考虑二分答案(所求长度具有二分性) 再用dp判断是否可行,这个 ...

  6. Vladik and cards CodeForces - 743E (状压)

    大意: 给定序列, 求选出一个最长的子序列, 使得任选两个[1,8]的数字, 在子序列中的出现次数差不超过1, 且子序列中相同数字连续. 正解是状压dp, 先二分转为判断[1,8]出现次数>=x ...

  7. 【codeforces 743E】Vladik and cards

    [题目链接]:http://codeforces.com/problemset/problem/743/E [题意] 给你n个数字; 这些数字都是1到8范围内的整数; 然后让你从中选出一个最长的子列; ...

  8. Codeforces Round #384 (Div. 2) //复习状压... 罚时爆炸 BOOM _DONE

    不想欠题了..... 多打打CF才知道自己智商不足啊... A. Vladik and flights 给你一个01串  相同之间随便飞 没有费用 不同的飞需要费用为  abs i-j 真是题意杀啊, ...

  9. 「算法笔记」状压 DP

    一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...

随机推荐

  1. day8 opencv3 ,没有GMG MOG

    Traceback (most recent call last): File , in <module> fgbg = cv2.createBackgroundSubtractorGMG ...

  2. windows下安装,配置redis以及可视化客户端redisClient的安装及基本使用

    一. Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你系统平台的实际情 ...

  3. Mybatis传递参数的三种方式

    第一种: Dao层使用@Param注解的方法 VersionBox getVersionByVersionNumAndVersionType(@Param("versionNum" ...

  4. 文件批量加密重命名--python脚本AND mysql命令行导入数据库

    在考试中学生交上来的报告,需要进行一下文件名加密,这样阅卷老师就不知道是谁的报告了 在百度帮助下,完成了加密和解密脚本, 加密 #!/usr/bin/python # -*- coding: utf- ...

  5. 使用Python的Requests库进行web接口测试

    1.Requests简介Requests 是使用 Apache2 Licensed 许可证的 HTTP 库.用 Python 编写,真正的为人类着想. Python 标准库中的 urllib2 模块提 ...

  6. POJ 3278 Catch That Cow (附有Runtime Error和Wrong Answer的常见原因)

    题目链接:http://poj.org/problem?id=3278 Catch That Cow Time Limit: 2000MS   Memory Limit: 65536K Total S ...

  7. Bellman-ford 模板

    #include<bits/stdc++.h> const int inf=0x3f3f3f3f; ; struct edge{ int u,v;//两个点 int w; //权值 Edg ...

  8. [python]序列的重复操作符

    当你需要需要一个序列的多份拷贝时,重复操作符非常有用,它的语法如下: sequence * copies_int In [1]: a = [1,2,3,4] In [2]: a * 5 Out[2]: ...

  9. 武汉天喻信息 移动安全领域 SE(Secure Element)

    产品简介: SE(Secure Element)为安全模块,是一台微型计算机,通过安全芯片和芯片操作系统(COS)实现数据安全存储.加解密运算等功能.SE可封装成各种形式,常见的有智能卡和嵌入式安全模 ...

  10. sprint1_11.15燃尽图(第二天)

    找相关的图片资料用于做点餐系统的界面 燃尽图: