Codeforces Round #384 (Div. 2) 734E(二分答案+状态压缩DP)
题目大意
给定一个序列an,序列中只有1~8的8个整数,让你选出一个子序列,满足下列两个要求
1.不同整数出现的次数相差小于等于1
2.子序列中整数分布是连续的,即子序列的整数必须是1,1,1....1,2,2,2.....2,2.......连续分布
做法:
那么我们可以二分不同整数出现的次数,假如说二分出现次数是L,那么可以证明有a个整数出现次数是L,有(8-a)个整数出现次数是L-1(同时不难证明L+1比L更优)
这样每个整数只有两种状态,要么选L个,要么选L-1个。
压缩决策s,s的第i位表示是否对整数i做出了决策
再用容器把每一个不同整数出现的序列记录下来,这样就可以进行dp了
设dp[i][s]表示从原序列扫到前i个数,已经做出了s的决策,出现L次的不同整数个数最大是多少
枚举对第k个整数做决策,dp[i][s]就可以转移到另外两个状态
dp[next(k, L-1)][s|(1<<k)] = max(itself, dp[i][s]);
dp[next(k, L)][s|(1<<k)] = max(itself, dp[i][s]+1);
其中next(k, L)是指从i开始,往后的第L个k的整数位置
然后取dp[1~n][(1<<8)-1]中的最大值,返回答案即可
另外如果最大值小于等于0(注意等于!!),说明不存在解,返回0即可。
需要注意的是,当l = 2都不可行的时候需要特判处理。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = ;
const int inf = 1e9;
int dp[maxn][<<], a[maxn], cur[maxn], n;
vector <int> in[];
int can(int L)
{
for(int i = ; i <= ; i++) cur[i] = ;
memset(dp, , sizeof(dp));
dp[][] = ;
for(int i = ; i <= n; i++)
{
for(int s = ; s < (<<); s++)
{
if(dp[i][s] < ) continue;
for(int k = ; k <= ; k++)
{
if(s & (<<(k-))) continue;
if(in[k].size() - cur[k] < L-) continue;
dp[in[k][cur[k] + L - ]][s|(<<(k-))] = max(dp[in[k][cur[k] + L - ]][s|(<<(k-))], dp[i][s]);
if(in[k].size() - cur[k] < L) continue;
dp[in[k][cur[k] + L - ]][s|(<<(k-))] = max(dp[in[k][cur[k] + L - ]][s|(<<(k-))], dp[i][s]+);
}
}
cur[a[i]]++;
}
int ans = -inf;
for(int i = ; i <= n ; i++) ans = max(ans, dp[i][(<<) - ]);
if(ans <= ) return ;
return ans * L + ( - ans)*(L-);
} int main()
{
//freopen("a.txt", "r", stdin);
cin>>n;
for(int i = ; i <= n; i++) cin>>a[i];
for(int i = ; i <= n; i++) in[a[i]].push_back(i);
int l = , r = n, ans = -inf;
while(l < r)
{
int mid = (l+r)>>;
if(can(mid)) l = mid+;
else r = mid;
}
if(can() == )
{
ans = ;
for(int i = ; i <= ; i++) if(in[i].size() > ) ans++;
cout<<ans<<endl;
}
else
{
ans = max(can(l), can(l-));
cout<<ans<<endl;
}
}
Codeforces Round #384 (Div. 2) 734E(二分答案+状态压缩DP)的更多相关文章
- Codeforces Round #262 (Div. 2)C(二分答案,延迟标记)
这是最大化最小值的一类问题,这类问题通常用二分法枚举答案就行了. 二分答案时,先确定答案肯定在哪个区间内.然后二分判断,关键在于怎么判断每次枚举的这个答案行不行. 我是用a[i]数组表示初始时花的高度 ...
- Codeforces Round #389 (Div. 2) 752E(二分答案)
题目大意 可以理解成有n个木板,可以选取木板将其劈成2半(如果长度是奇数,就切成x和x+1),切完之后还可以再切 然后你要把这n个木板切成更多的木板,然后从中选择k个,使得这k个木板的最小长度尽量大 ...
- 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 #404 (Div. 2) C 二分查找
Codeforces Round #404 (Div. 2) 题意:对于 n and m (1 ≤ n, m ≤ 10^18) 找到 1) [n<= m] cout<<n; 2) ...
- Codeforces Round #384(div 2)
A 题意:有n个机场处于一直线上,可两两到达,每个机场只可能属于两家公司中的一家(用0,1表示),现在要从a机场到b机场,可任意次转机.若机场i与机场j从属同一公司,则费用为0,否则费用为1.问最小费 ...
- Codeforces Round #267 (Div. 2) C. George and Job(DP)补题
Codeforces Round #267 (Div. 2) C. George and Job题目链接请点击~ The new ITone 6 has been released recently ...
- Codeforces Round #538 (Div. 2) D. Flood Fill 【区间dp || LPS (最长回文序列)】
任意门:http://codeforces.com/contest/1114/problem/D D. Flood Fill time limit per test 2 seconds memory ...
- Codeforces Round #324 (Div. 2) C (二分)
题目链接:http://codeforces.com/contest/734/problem/C 题意: 玩一个游戏,一开始升一级需要t秒时间,现在有a, b两种魔法,两种魔法分别有m1, m2种效果 ...
- Codeforces Round #377 (Div. 2)D(二分)
题目链接:http://codeforces.com/contest/732/problem/D 题意: 在m天中要考k个课程, 数组a中有m个元素,表示第a[i]表示第i天可以进行哪门考试,若a[i ...
随机推荐
- 线段树的应用xx中学模拟lites
跟昨天那个自己写的,没有按照模板来的一看风格就不相类似,今天模拟赛的时候就是用的我的那个自己YY的代码,才拿了10分.个人认为关键的问题应该在于对于数据的处理太过繁琐了,所以回来之后,就拿了大佬的程序 ...
- django连接mysql数据库配置,出现no module named mysqldb报错
作为一个菜鸟运维也是要有梦想的,万一学会了python走向人生巅峰了呢.好吧,都是瞎想,今天主要介绍下django配置,最近也开始摸索这个牛b框架了,当然大佬肯定不屑一顾,都是照顾照顾我们这些菜鸟初学 ...
- Servlet学习笔记01——什么是servlet?
1.什么是Servlet? sun公司制订的一种用来扩展web服务器功能的组件规范. (1)扩展web服务器功能 早期的web服务器(apache web server,iis) 只能处理静态资源的请 ...
- 交换机基础设置之vtp管理vlan设置
vtp的设置有三种模式1:server模式,负责创建,删除vlan(服务器模式) 2:client模式,负责接收并转发来自server的信息(客户机模式) 3:transparent模式,只负责转发, ...
- 给树莓派Raspbian stretch版本修改软件源
树莓派最新的系统版本是stretch,试了阿里和网易的软件源都不行,最后试了清华的可以 deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbia ...
- 【c学习-4】
//递归函数,调用自身 #include<stdio.h> int fibFunc(int n) { || n==){ ; }else{ )+fibFunc(n-); } } int ma ...
- css3 媒体查询的学习。
1.什么是媒体查询 媒体查询可以让我们根据设备显示器的特性(如视口宽度.屏幕比例.设备方向:横向或纵向)为其设定CSS样式,媒体查询由媒体类型和一个或多个检测媒体特性的条件表达式组成.媒体查询中可用于 ...
- linux 共享内存
共享内存是最高效的IPC机制,因为它不涉及进程之间的任何数据传输.这种高效带来的问题是,我们必须用其他手段来同步进程对共享内存的访问,否则会产生竞态条件.所以,共享内存通常和其他进程间通信方式一起使用 ...
- 裸机——I2C
网上搜了些资料,碍于智商和基础,看不懂, 只有将S5PV210 数据手册关于I2C的部分,翻译记录下,留到以后用. 1.OVERVIEW The S5PV210 RISC microprocessor ...
- python基础之模块part1
模块: 模块本质上就是一个Python程序. 所有说是对象的,一定可以通过 对象.方法 来实现某些操作. 模块种类: 内置模块 第三方模块 自定义模块 import在查找模块的顺序:内置模块--- ...