C. Large Queue
用队列维护二元组 (值,数量),本质上和ABC247D一样
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int Q;
cin >> Q;
queue<pair<int, int>> q;
rep(i, Q) {
int type;
cin >> type;
if (type == 1) {
int c, x;
cin >> c >> x;
q.emplace(x, c);
}
else {
int k;
cin >> k;
ll ans = 0;
while (k) {
auto [x, c] = q.front();
if (c <= k) {
ans += (ll)x*c;
k -= c;
q.pop();
}
else {
ans += (ll)x*k;
q.front().second -= k;
k = 0;
}
}
cout << ans << '\n';
}
}
return 0;
}
D. Make Geometric Sequence
先将序列按绝对值大小做升序排序
然后利用等比数列的判定条件直接判定即可
由于这里的比值可能是分数,所以可以转化成乘法
还需注意需要特判所有数的绝对值都相同的情况:考虑正数和负数交叉排列,最后最多剩下一个整数或负数
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
bool solve() {
int n;
cin >> n;
vector<ll> a(n);
rep(i, n) cin >> a[i];
ranges::sort(a, [](ll x, ll y) { return abs(x) < abs(y); });
{
bool ok = true;
rep(i, n-2) {
if (a[i]*a[i+2] != a[i+1]*a[i+1]) ok = false;
}
if (ok) return true;
}
if (abs(a[0]) == abs(a.back())) {
int pos = 0, neg = 0;
rep(i, n) if (a[i] < 0) neg++; else pos++;
if (abs(neg-pos) <= 1) return true;
}
return false;
}
int main() {
int t;
cin >> t;
while (t--) {
if (solve()) puts("Yes");
else puts("No");
}
return 0;
}
E. Reverse 2^i
本题要求在不改变对战组合的前提下重排锦标赛对战表。关键在于:通过整体翻转和分段反转实现区间反转。
具体做法:
- 操作原理:
- 将整个对战表完全反转
- 再将前半段和后半段分别独立反转
- 即可实现前半段和后半段的位置交换
- 最优策略:
- 分别求出前半段和后半段的字典序最小排列
- 将字典序较小的段放在前面

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
void solve() {
int n;
cin >> n;
int n2 = 1<<n;
vector<int> p(n2);
rep(i, n2) cin >> p[i];
for (int w = 1; w < n2; w <<= 1) {
for (int l = 0; l < n2; l += w*2) {
if (p[l] > p[l+w]) {
rep(i, w) swap(p[l+i], p[l+i+w]);
}
}
}
rep(i, n2) cout << p[i] << " \n"[i == n2-1];
}
int main() {
int t;
cin >> t;
while (t--) solve();
return 0;
}
还有一种思路是看区间中的最小值在左半段还是右半段,如果在右半段,就将整个区间翻转
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
void solve() {
int n;
cin >> n;
int n2 = 1<<n;
vector<int> p(n2);
rep(i, n2) cin >> p[i];
auto f = [&](auto& f, int l, int r) {
if (r-l == 1) return;
int c = (l+r)/2;
int minl = *min_element(p.begin()+l, p.begin()+c);
int minr = *min_element(p.begin()+c, p.begin()+r);
if (minl > minr) reverse(p.begin()+l, p.begin()+r);
f(f, l, c);
f(f, c, r);
};
f(f, 0, n2);
rep(i, n2) cout << p[i] << " \n"[i == n2-1];
}
int main() {
int t;
cin >> t;
while (t--) solve();
return 0;
}
F. No Passage
在青木不干扰时,标准的bfs
在有干扰的情况下,需要改良bfs算法 —— 当某个点第二次被访问时执行以下操作:
- 更新该点的最短距离
- 重新将其加入队列
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
using P = pair<int, int>;
const int di[] = {-1, 0, 1, 0};
const int dj[] = {0, 1, 0, -1};
int main() {
int h, w, k;
cin >> h >> w >> k;
const int INF = 1001001001;
vector dist(h, vector<int>(w, INF));
vector checked(h, vector<bool>(w));
queue<P> q;
rep(i, k) {
int r, c;
cin >> r >> c;
--r; --c;
dist[r][c] = 0;
q.emplace(r, c);
}
while (q.size()) {
auto [i, j] = q.front(); q.pop();
rep(v, 4) {
int ni = i+di[v], nj = j+dj[v];
if (ni < 0 or nj < 0 or ni >= h or nj >= w) continue;
if (dist[ni][nj] != INF) continue;
if (checked[ni][nj]) {
dist[ni][nj] = dist[i][j]+1;
q.emplace(ni, nj);
}
else checked[ni][nj] = true;
}
}
ll ans = 0;
rep(i, h)rep(j, w) if (dist[i][j] != INF) ans += dist[i][j];
cout << ans << '\n';
return 0;
}
G. Big Banned Grid
分割平面图,找一条路径将 \((1, 1)\) 和 \((H, W)\) 分隔开即可
可以用bfs来实现
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using P = pair<int, int>;
int main() {
int h, w, k;
cin >> h >> w >> k;
vector<P> ps;
map<P, int> mp;
rep(i, k) {
int r, c;
cin >> r >> c;
ps.emplace_back(r, c);
mp[ps[i]] = i;
}
vector<bool> used(k);
queue<int> q;
rep(i, k) {
auto [r, c] = ps[i];
if (r == 1 or c == w) {
used[i] = true;
q.push(i);
}
}
while (q.size()) {
int v = q.front(); q.pop();
auto [i, j] = ps[v];
for (int di = -1; di <= 1; ++di) {
for (int dj = -1; dj <= 1; ++dj) {
int ni = i+di, nj = j+dj;
if (!mp.count(P(ni, nj))) continue;
int u = mp[P(ni, nj)];
if (used[u]) continue;
used[u] = true;
q.push(u);
}
}
}
rep(i, k) if (used[i]) {
auto [r, c] = ps[i];
if (r == h or c == 1) {
puts("No");
return 0;
}
}
puts("Yes");
return 0;
}
浙公网安备 33010602011771号