AtCoder Beginner Contest 215 - ABC215
E - Chain Contestant
题意
给出一个由 种大写字母 组成的字符串 ,长度为 ,求 有多少个下标序列满足下列条件:
令下标序列所对应的 的子序列为 ,满足同一种字母在 中都是连续出现的,如:AAABBCCC
满足条件,但 AABBACCC
就不满足条件,因为字母 A
不连续。
数据范围:
思路
看到字母的类型只有10种,而且每一个状态下要保证之前没有出现过该数字,所以可以用dp的一维保存之前出现过的数字,由于最后一位是可以连续的,所以dp还有一维存储最后一位的数字。
先将字母对应成数字 。
设 ,表示前 个字符组成的子序列中,最后一位为 ,且使用子序列中包含了集合 中的数字。
设 ,则有如下转移:
-
代表第 位不取。
-
代表取第 位,且是上一位取值也是 。
-
代表取第 位,且是第一次取 。
-
代表只取第 位。
则,。
总复杂度 。
由于dp的第一维可以滚掉,所以就少开了一维。
点击显/隐代码
#include <bits/stdc++.h>
#define db double
#define ll long long
#define int ll
#define vi vector<int>
#define vii vector<vi >
#define pii pair<int, int>
#define vp vector<pii >
#define vip vector<vp >
#define mkp make_pair
#define pb push_back
#define Case(x) cout << "Case #" << x << ": "
using namespace std;
const int INF = 0x3f3f3f3f;
const int P = 998244353;
const int N = 1e3 + 10;
int f[10][1<<10], tmp[10][1<<10];
signed main(){
#ifdef _DEBUG
// FILE *file = freopen("out", "w", stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
string s;
cin >> s;
for (int i = 0; i < n; i++) {
int x = s[i] - 'A';
memcpy(tmp, f, sizeof(f));
for (int k = 0; k < (1<<10); k++) {
f[x][k] = (f[x][k] + tmp[x][k]) % P;
if ((k >> x & 1) == 0) {
for (int j = 0; j < 10; j++) {
f[x][k | (1<<x)] = (f[x][k | (1<<x)] + tmp[j][k]) % P;
}
}
}
f[x][1<<x] = (f[x][1<<x] + 1) % P;
}
int ans = 0;
for (int j = 0; j < 10; j++) {
for (int k = 0; k < (1<<10); k++) {
ans = (ans + f[j][k]) % P;
}
}
cout << ans << '\n';
return 0;
}
F - Dist Max 2
题意
给出 个二维坐标 ,定义两个点 的距离为 。
(切比雪夫距离是取 )
找到这 个点中两个点的距离的最大值。
数据范围:。
思路
求最大化最小值,考虑二分答案的方法,由于每个点有 两个参数,故可以先对 从小到大排序。
设答案为 ,则一定存在 使得, 并且 ,
由于当前 有序,则可以从小到大顺次枚举,对于当前枚举到的 ,如果 满足 ,则有 ,故 这些元素的 值都已经满足条件,只需找到满足条件的 值,由于满足条件的值一定是边界值,也就是最大或最小值,于是再维护 对应 坐标的最大值和最小值,最终判断是否有满足条件的 值即可。
总复杂度 。
点击显/隐代码
#include <bits/stdc++.h>
#define db double
#define ll long long
#define vi vector<int>
#define vii vector<vi >
#define pii pair<int, int>
#define vp vector<pii >
#define vip vector<vp >
#define mkp make_pair
#define pb push_back
#define Case(x) cout << "Case #" << x << ": "
using namespace std;
const int INF = 0x3f3f3f3f;
const int P = 998244353;
signed main(){
#ifdef _DEBUG
// FILE *file = freopen("out", "w", stdout);
#endif
int n;
scanf("%d", &n);
vp a(n);
for (int i = 0; i < n; i++) {
scanf("%d %d", &a[i].first, &a[i].second);
}
sort(a.begin(), a.end());
int l = 0, r = 1e9;
while (l <= r) {
int mid = (l + r) >> 1;
int fg = 0, mx = 0, mn = 1e9;
queue<pii> q;
for (auto p : a) {
while (!q.empty()) {
if (p.first - q.front().first < mid) break;
mx = max(mx, q.front().second);
mn = min(mn, q.front().second);
q.pop();
}
if (p.second - mn >= mid || mx - p.second >= mid) {
fg = 1;
break;
}
q.push(p);
}
if (fg) l = mid + 1;
else r = mid - 1;
}
printf("%d\n", r);
return 0;
}
AtCoder Beginner Contest 215 - ABC215
https://wty-yy.github.io/posts/51581/