分类
标签
2-SAT AC自动机 BFS CDQ dfs DP fail树 FFT FFT&NTT FWT hash KD-Tree KMP LCA SPFA STL Tarjan Treap Trie 主席树 乱搞 二分 二分图匹配 二分答案 二维SPFA 交互 位运算 其他 最小生成树 分块 区间DP 半平面交 博弈论 可持久化 可持久化Trie树 后缀数组 图库 平衡树 并查集 插头DP 数学 数论 无旋Treap 日记 暴力 权值树状数组 栈 树DP 树套树 树状数组 树贪心 概率DP 模拟 欧拉定理 点分治 状压DP 生成函数 矩阵乘 线性规划 线段树 组合 网络流 群论 莫比乌斯反演 计算几何 贪心 费用流 高斯消元
670 字
3 分钟
Codeforces 743E Vladik and cards
题目描述
Vladik在回家的路上无聊,决定玩下面的游戏:他拿了n张牌在他面前排成一个序列,每张牌上都有一个不超过8的正整数,他决定找到满足以下条件的牌的最长子序列:
在这个序列中,[1,8]每个数字出现的次数之差的绝对值不超过1;
相同的数字必须连续,输出最长子序列的长度。例如,子序列[1, 1, 2, 2]满足第2个条件,但是子序列 [1, 2, 2, 1]就不满足(注意,子序列[1, 1, 2, 2]不满足第一个条件)。
请帮助Vladik找到满足这两个条件的最长子序列的长度。
输入
第一行包含单个整数n(1≤n≤1000) - Vladik序列中的牌数。
第二行包含不超过8的n个正整数的序列 - 每个数空格隔开
输出
输出一个整数,即满足两个条件的子序列的最大长度
样例输入
- sample input 1:
3
1 1 1
- sample input 2:
8
8 7 6 5 4 3 2 1
- sample input 3:
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
样例输出
sample output 1:
1
sample output 2:
8
sample output 3:
17
题解请参考CodeForces743E. Vladik and cards 二分+装压dp
/*
* @Author: WildRage
* @Date: 2017-07-02 16:07:15
* @Last Modified by: WildRage
* @Last Modified time: 2017-07-02 17:58:06
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int a[1005], sum[10][1005],n;
int DP[1005][300];
bool had[10];
int N = (1 << 8) - 1;
vector<int> in[10];
int get_num(int p, int len)
{
int now = lower_bound(in[a[p]].begin(), in[a[p]].end(), p) - in[a[p]].begin();
int ans = now + len - 1;
if (in[a[p]].size() - 1 < ans)
return -1;
return in[a[p]][ans];
}
int Judge(int len)
{
memset(DP, 0, sizeof(DP));
for (int i = 0; i < n; i++)
{
int to = get_num(i + 1, len);
if (to != -1)
DP[to][(1 << (a[i + 1] - 1))] = max(DP[i][0] + len, DP[to][1 << (a[i + 1] - 1)]);
to = get_num(i + 1, len + 1);
if (to != -1)
DP[to][(1 << (a[i + 1] - 1))] = max(DP[i][0] + len + 1, DP[to][(1 << (a[i + 1] - 1))]);
for (int j = 1; j < N; j++)
{
if (DP[i][j])
{
DP[i + 1][j] = max(DP[i + 1][j], DP[i][j]);
if (j & (1 << (a[i + 1] - 1)))
continue;
to = get_num(i + 1, len);
if (to != -1)
DP[to][j | (1 << (a[i + 1] - 1))] = max(DP[i][j] + len, DP[to][j | (1 << (a[i + 1] - 1))]);
to = get_num(i + 1, len + 1);
if (to != -1)
DP[to][j | (1 << (a[i + 1] - 1))] = max(DP[i][j] + len + 1, DP[to][j | (1 << (a[i + 1] - 1))]);
}
DP[i + 1][N] = max(DP[i + 1][N], DP[i][N]);
}
}
return DP[n][N];
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", a + i);
had[a[i]] = 1;
in[a[i]].push_back(i);
}
int ans = 0;
for(int i=1;i<=8;i++)if(had[i])ans++;
int l = 1, r = 256;
while (l <= r)
{
int mid = l + r >> 1;
int x = Judge(mid);
ans = max(x, ans);
if (x)
l = mid + 1;
else
r = mid - 1;
}
printf("%d", ans);
}
Codeforces 743E Vladik and cards
https://www.nekomio.com/posts/27/