Aoao Round 2 比赛总结
分数: \(100 + 25 + 20 + 0 = 145\)
好一个神秘 seq 赛。
T1
不难发现,一个符合要求的序列需要是连续的,且其中比 \(b\) 大的数和比 \(b\) 小的数数量相等。
因此,我们可以以 \(b\) 为起点,分别向两侧扫描,把比 \(b\) 小的数记作 \(-1\),比 \(b\) 大的数记作 \(1\),并分别计算其前缀和。当左侧的某个前缀和和右侧的某个前缀和成相反数时,此时左右比 \(b\) 大和比 \(b\) 小的数的数量就会恰好相等,那么就找到了一个符合要求的序列。
在代码实现中,为了方便,当在 \(b\) 右侧进行扫描时,我们可以把比 \(b\) 大的记作 \(-1\),比它小的记作 \(1\)(与上面的描述相反),然后把左右两侧前缀和分别放入两个桶中。然后左右两个桶相同位置的数的乘积之和即为答案。
别忘了开 long long,不然就会挂掉 55 分。
#include <bits/stdc++.h>
typedef long long ll;
const int N = 2e5+10;
int a[N], n, posB, b;
ll val[N], lBuc[2 * N + 10], rBuc[2 * N + 10];
ll ans = 0;
int main() {
freopen("empty.in", "r", stdin);
freopen("empty.out", "w", stdout);
std::ios::sync_with_stdio(false); std::cin.tie(0);
std::cin >> n >> b;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
if (a[i] == b) posB = i;
}
for (int i = posB - 1; i >= 1; i--) {
if (a[i] < b) {
val[i] = val[i+1] - 1;
} else val[i] = val[i+1] + 1;
}
for (int i = posB + 1; i <= n; i++) {
if (a[i] < b) val[i] = val[i-1] + 1;
else val[i] = val[i-1]-1;
}
const int ADD = 2e5+10;
for (int i = 1; i <= posB; i++) {
lBuc[val[i] + ADD]++;
}
for (int i = posB; i <= n; i++) {
rBuc[val[i] + ADD]++;
}
for (int i = 0; i <= 2 * N; i++) {
ans += lBuc[i] * rBuc[i];
}
std::cout << ans << '\n';
return 0;
}
T2
当我看到题解时,虎躯一震——这道题竟然是图论?!
是的,这是一道典型的图论建模题目。我们可以把每个整数当成图上的一个节点,然后定义:相邻的两个整数的二进制只有一位不同 (有点像格雷码)。
可以注意到 \(\max(\operatorname{nailong}(x, y)) + \min(\operatorname{nailong}(\sim x, y)) = m\)。 考虑 BFS,对序列中的每个数取反,并以其为原点开始。每次搜相邻的整数,如果这个数还没有被搜索过,就记录其步数,并将其加入队列。然后,答案就是 \(m\) 与序列中每个数步数的最小值的差。
#include <bits/stdc++.h>
typedef long long ll;
const int N = 1.1e6+10;
int a[N], n, m, step[N], vis[N];
int main() {
freopen("purple.in", "r", stdin);
freopen("purple.out", "w", stdout);
std::ios::sync_with_stdio(false); std::cin.tie(0);
std::cin >> n >> m;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
}
std::queue<int> q;
for (int i = 1; i <= n; i++) {
q.push(((1 << m) - 1) ^ a[i]);
vis[(((1 << m) - 1) ^ a[i])] = true;
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < m; i++) {
int v = u ^ (1 << i);
if (!vis[v]) {
vis[v] = true;
q.push(v);
step[v] = step[u] + 1;
}
}
}
for (int i = 1; i <= n; i++) {
std::cout << m - step[a[i]] << ' ';
}
return 0;
}

浙公网安备 33010602011771号