CF811C 火车旅行
1 CF811C 火车旅行
2 题目描述
时间限制 \(2s\) | 空间限制 \(256M\)
\(Vladik\) 经常坐火车旅行,他对于一些旅程记忆深刻。\(Vladik\) 在起始的火车站,包括他自己在内一共有 \(n\) 个旅客想上火车。他们已经按照一定的顺序排成一列,他们每个人的目标城市的代码 \(a_i\) 已知。列车长从原始顺序中选择了一些不相交区间(这些区间不能覆盖整个序列)的数字。在同一个区间的旅客被分在同一个车厢里面。在区间选择的时候如果至少有一个旅客的目标城市是 \(x\),那么所有的想去城市 \(x\) 的旅客都会被分在同一个车厢里面,也就是说他们只能在同一个区间内。注意所有去城市 \(x\) 的旅客要么一起去同一个车厢里面,要么就哪里都不去。从位置 \(l\) 到 \(r\) 的旅客的幸福指数等于 \(l\) 和 \(r\) 之间的旅客不同的目标城市代码异或而成。这列火车旅行的幸福指数由每一段幸福指数的累加和构成。帮助 \(Vladik\) 计算最大可能的幸福指数。
数据范围:\(1 ≤ n ≤ 5000\)
3 题解
由于这道题数据范围较小,可以允许我们进行 \(O(n^2)\) 级别的操作。我们就可以考虑枚举 \(l, r\),计算出区间 \([l, r]\) 的异或和 \(sum_{l, r}\)。但是题目中还规定所有目标城市相同的乘客都在同一车厢内。我们可以预处理出对于某目标城市,最左和最右的乘客。如果某区间中去某个城市的乘客没有全部包括,那么我们将该区间的异或和定义为 \(-INF\)。
此时我们考虑使用 \(dp\) 计算最大的区间和。设 \(dp_i\) 表示考虑前 \(i\) 个乘客时最大的舒适度,则有 $dp_i = \max(\max_{j = 1}^{i} \limits dp_{j-1} + sum_{j, i}, dp_{i-1}) $。
4 代码(空格警告):
#include <iostream>
#include <cstring>
using namespace std;
const int N = 5e3+10;
int n;
int a[N], sum[N][N], dp[N], xxor[N][N];
int maxn[N], minn[N], maxx, minnn;
bool f[N], f2[N];
int main()
{
memset(maxn, -0x3f, sizeof(maxn));
memset(minn, 0x3f, sizeof(minn));
memset(sum, -0x3f, sizeof(sum));
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++)
{
maxn[a[i]] = max(maxn[a[i]], i);
minn[a[i]] = min(minn[a[i]], i);
}
for (int i = 1; i <= n; i++)
{
memset(f2, 0, sizeof(f2));
xxor[i][i] = a[i];
f2[a[i]] = 1;
for (int j = i+1; j <= n; j++)
{
if (!f2[a[j]])
{
xxor[i][j] = xxor[i][j-1] ^ a[j];
f2[a[j]] = 1;
}
else xxor[i][j] = xxor[i][j-1];
}
}
for (int i = 1; i <= n; i++)
{
minnn = 0x3f3f3f3f;
maxx = -0x3f3f3f3f;
if (minn[a[i]] < i) continue;
if (maxn[a[i]] == i)
{
sum[i][i] = xxor[i][i];
}
minnn = min(minnn, minn[a[i]]);
maxx = max(maxx, maxn[a[i]]);
for (int j = i+1; j <= n; j++)
{
minnn = min(minnn, minn[a[j]]);
maxx = max(maxx, maxn[a[j]]);
if (i > minnn || j < maxx) continue;
sum[i][j] = xxor[i][j];
}
}
for (int i = 1; i <= n; i++)
{
dp[i] = dp[i-1];
for (int j = 1; j <= i; j++)
{
dp[i] = max(dp[i], dp[j-1] + sum[j][i]);
}
}
cout << dp[n];
return 0;
}