2023.6.19 每日一题
原题链接
A: Educational Codeforces Round 103 (Rated for Div. 2) - E
B: Codeforces Round 744 (Div. 3) - F
A. Pattern Matching - 2300
题目大意
给定 \(n\) 个模式串和 \(m\) 个匹配串,模式串中可能含有通配符_
,现在需要对模式串重新排列,使得匹配上每一个匹配串的第一个模式串是第 \(t_i\) 个 ,如果可以得到满足,那么输出排序结果。
解题思路
我们需要匹配到的第一个模式串恰好排第 \(t_i\) 位,那么在所有与这个匹配串匹配的串中,这个串需要放最前面,那么需要考虑跑一个拓扑排序,同时为了降低复杂度,我们可以从匹配串入手,往模式串连边。因为这样每个匹配串最多建立 \(2^4\) 条边,不会TLE。
AC Code
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
vector<int> v[N];
map<string, int> mp;
vector<int> path;
bool vis[N];
bool ever[N];
void dfs(int u) {
if (vis[u]) {
cout << "NO" << endl;
exit(0);
}
if (ever[u]) return;
vis[u] = ever[u] = true;
for (auto i : v[u]) {
dfs(i);
}
vis[u] = false;
path.push_back(u);
}
void solve() {
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; ++i) {
string s;
cin >> s;
mp[s] = i;
}
bool flag = true;
for (int i = 1; i <= m; ++i) {
string s;
int x;
cin >> s >> x;
flag = true;
for (int j = 0; j < (1 << k); ++j) {
string t = s;
for (int l = 0; l < k; ++l) {
if ((j >> l) & 1) {
t[l] = '_';
}
}
if (mp.contains(t)) {
if (mp[t] == x) {
flag = false;
} else {
v[mp[t]].push_back(x);
}
}
}
if (flag) {
cout << "NO" << endl;
return;
}
}
for (int i = 1; i <= n; ++i) {
dfs(i);
}
cout << "YES" << endl;
for (int i = 0; i < n; ++i) {
cout << path[i] << ' ';
}
}
signed main() {
ios;
int T = 1;
// cin >> T;
while (T--) {
solve();
}
}
B. Array Stabilization (AND version) - 1700
题目大意
给定一个下标从 \(0\) 开始的数组,反复做如下操作:
- 将数组向右移动 \(d\) 位得到 \(b\) 数组。
- 将数组每一位替换成 \(a_i\ \&\ b_i\)。
直到数组不再发生变化为止,问如果能使得最后的数组全为 \(0\),一共经过了多少步。
解题思路
我们使用一个set存储 \(0\) 的位置模拟这个过程。每次遍历的时候,记录新数组与原来数组相比,\(0\) 的数量改变了多少,同时对我们的位置set进行更新即可。
AC Code
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
const int MOD = 1e9 + 7;
int a[N];
set<int> st;
void solve() {
int n, d;
st.clear();
LL res = 0;
cin >> n >> d;
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
int cnt = 0;
for (int i = 0; i < n; ++i) {
if (!a[i]) {
cnt++;
if (a[(i + d) % n]) {
st.insert(i);
}
}
}
while (cnt < n) {
set<int> tmp1, tmp2;
res++;
if (st.empty()) {
cout << -1 << endl;
return;
}
for (int i : st) {
cnt++;
tmp1.insert(i);
a[(i + d) % n] = 0;
if (a[(i + (d << 1)) % n]) {
tmp2.insert((i + d) % n);
}
}
for (int i : tmp1) {
st.erase(i);
}
for (int i : tmp2) {
st.insert(i);
}
}
cout << res << endl;
}
signed main() {
ios;
int T = 1;
cin >> T;
while (T--) {
solve();
}
}