AcWing第4场周赛题解
A. AcWing 3694. A还是B
题目链接:https://www.acwing.com/problem/content/3697/
题目大意:判断字符串中'A'还是'B'出现地多。
解题思路:循环一遍记个数。
示例程序:
#include <bits/stdc++.h>
using namespace std;
string s;
int n, a, b;
int main() {
cin >> n >> s;
for (auto c : s)
(c == 'A') ? a++ : b++;
if (a == b) puts("T");
else if (a > b) puts("A");
else puts("B");
return 0;
}
AcWing 3695. 扩充序列
题目链接:https://www.acwing.com/problem/content/3698/
题目大意:求序列扩充n次的第k个数。
解题思路:可以基于分治用递归做,也可以用二进制做。因为这道题是cf原题,我递归写过了,所以这里用二进制做,但其实都是基于分治思想。
示例程序:
#include <bits/stdc++.h>
using namespace std;
int n;
long long k;
int main() {
cin >> n >> k;
for (int i = n-1; i >= 0; i--) {
if (!(k ^ (1LL<<i))) {
cout << i+1 << endl;
break;
}
k &= (1LL<<i)-1;
}
return 0;
}
C. AcWing 3696. 构造有向无环图
题目链接:https://www.acwing.com/problem/content/3699/
题目大意:给图上一些边确定方向,使其成为一个 DAG。
解题思路:拓扑排序两次,第一次给每个节点一个时间戳,然后根据时间戳的大小(小的往大的连一条边),第二次(连好边后)看看能不能正常拓扑排序,可以的话就 “YES”;不然就 “NO”。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int T, n, m, t[maxn], x[maxn], y[maxn], in[maxn], tt[maxn]; // tt[i]表示节点i的时间戳
vector<int> g[maxn];
queue<int> que;
bool check() {
int idx = 0; // 时间戳
while (!que.empty()) que.pop();
for (int i = 1; i <= n; i++) if (!in[i]) {
tt[i] = ++idx;
que.push(i);
}
while (!que.empty()) {
int u = que.front();
que.pop();
for (auto v : g[u]) {
in[v]--;
if (!in[v]) {
tt[v] = ++idx;
que.push(v);
}
}
}
return idx == n;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> T;
while (T--) {
cin >> n >> m;
for (int i = 0; i < m; i++)
cin >> t[i] >> x[i] >> y[i];
// 1-st topological sorting
for (int i = 1; i <= n; i++) g[i].clear(), in[i] = 0;
for (int i = 0; i < m; i++)
if (t[i]) g[x[i]].push_back(y[i]), in[y[i]]++;
if (!check()) {
cout << "NO" << endl;
continue;
}
// 根据原来的有向边及时间戳重新建图
for (int i = 1; i <= n; i++)
g[i].clear();
for (int i = 0; i < m; i++) {
int u = x[i], v = y[i];
if (!t[i] && tt[u] > tt[v]) swap(u, v);
g[u].push_back(v);
in[v]++;
}
// 2-st topological sorting
if (!check()) {
cout << "NO" << endl;
} else {
cout << "YES" << endl;
// 输出边的信息
for (int i = 0; i < m; i++) {
int u = x[i], v = y[i];
if (!t[i] && tt[u] > tt[v]) swap(u, v);
cout << u << " " << v << endl;
}
}
}
return 0;
}