AcWing第四场周赛
比赛链接:Here
AcWing 3694. A还是B
签到题
void solve() {
int n; string s;
cin >> n >> s;
int t = count(s.begin(), s.end(), 'A');
if (t * 2 == n)cout << "T";
else if (t * 2 < n)cout << "B";
else cout << "A";
}
AcWing 3695. 扩充序列
思维构造题
这题目本身并不难,只不过出得有 一些 “委婉”罢了。
先来研究一下题目,每次“扩充”都会将序列复制一次,然后在中间会插入一个还未使用过的最小正整数。
其实“还未使用过的 最小 正整数”,其实不过就是添加原数列中最大的值+1。
再看,扩充 \(n\) 次,就会将原序列变为 \(2^n + 1\) 。
那么对于 \(k\) 来说,只需判断小于 \(2^x\) 即可
输出 \(x + 1\)
注意点:long long
void solve() {
ll n, k; cin >> n >> k;
int cnt = 1;
while (!(k & 1))k >>= 1, cnt++;
cout << cnt << "\n";
}
AcWing 3696. 构造有向无环图
对图进行拓扑排序,其中我们只加有向边,不考虑无向边。
若无法拓扑排序,则说明有向边已经构成了环,输出 NO。
否则,在拓扑排序的时候,对于所有点,我们可以得到一个时间戳,而对于所有无向边,将其方向定位从时间戳小的连向时间戳大的边即可。
时间复杂度:\(\mathcal{O}(n + m)\)
typedef pair<int, int> E;
const int N = 200005;
int n, m;
int d[N], p[N];
vector<int> g[N];
bool topo() {
static int q[N], hh, tt, s;
hh = tt = 0, s = 0;
for (int x = 1; x <= n; ++x)
if (!d[x]) q[tt++] = x;
while (hh != tt) {
int t = q[hh++];
++s, p[t] = s;
for (int i = 0; i < g[t].size(); ++i) {
int v = g[t][i];
if (!--d[v]) q[tt++] = v;
}
}
return s == n;
}
void solve() {
cin >> n >> m;
memset(d + 1, 0, n << 2);
memset(p + 1, 0, n << 2);
for (int i = 1; i <= n; ++i) g[i].clear();
vector<E> res;
for (int i = 0; i < m; ++i) {
int a, b, t;
cin >> t >> a >> b;
res.push_back({a, b});
if (t) g[a].push_back(b), ++d[b];
}
if (topo()) {
puts("YES");
for (auto [a, b] : res) {
if (p[a] > p[b]) swap(a, b);
printf("%d %d\n", a, b);
}
} else puts("NO");
}