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 ...
随机推荐
- Mybatis查询报错:There is no getter for property named '*' in 'class java.lang.String
问题: 执行查询时报错:There is no getter for property named '*' in 'class java.lang.String 原因: 传过去的参数为识别.本例为 p ...
- RDVTabBarController--可自由定制的iOS底部导航控件
RDVTabBarController:一个十分完善的tabBarController,可以自定义角标个数,爽的停不下来. RDVTabBarController地址:RDVTabBarControl ...
- JavaScript的执行机制
JavaScript是单线程的,任务的执行时自上而下的,这就有了一个问题,当遇到一个比较耗时的任务时,下面的代码就会被阻塞,这就意味着卡死.所以js是有异步的,它的实现主要是通过事件循环(event ...
- phonegap二维码扫描插件
原文出处:http://rensanning.iteye.com/blog/2034026 谈谈我使用这个的体会吧; git地址 https://github.com/wildabeast/Barco ...
- 面向对象封装的web服务器
import socket import re import os import sys # 由于前面太繁琐,可以用类封装一下,也可以分几个模块 class HttpServer(object): d ...
- 统计寄存器AX中1 的个数
;==================================== ; 统计寄存器AX中1 的个数 DATAS segment DATAS ends CODES segment START: ...
- js三目运算符执行多个条件
三元运算符的结果语句可以执行多个操作,每个操作用逗号分隔就可以,例子如下: var a=1: a>5?(alert(1),alert(2)):(alert(3),alert(4))
- PAT (Basic Level) Practice 1023 组个最小数
个人练习 给定数字 0-9 各若干个.你可以以任意顺序排列这些数字,但必须全部使用.目标是使得最后得到的数尽可能小(注意 0 不能做首位).例如:给定两个 0,两个 1,三个 5,一个 8,我们得到的 ...
- 关于C、内存、栈的一些杂谈
c的程序要手动管理内存的,所有的数据(结构)都可以分为两种存储方式,连续存储,顾名思义申请一片连续的内存以供使用(数组.结构体.共用体.栈.队列):非连续存储,顾名思义断断续续的的存储,那有一点这有一 ...
- \r \r\n \t的区别
\n 软回车: 在Windows 中表示换行且回到下一行的最开始位置.相当于Mac OS 里的 \r 的效果. 在Linux.unix 中只表示换行,但不会回到下一行的开始位置. ...