2025暑假提高级冲刺集训班-8 题解
__xxy_free_ioi__ · · 个人记录
坠机了。
T1 [ARC134A] Bridge and Sheets
模拟题,不讲,但注意不要用
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int, int>
#define VI vector<int>
#define sz(a) a.size()
#define all(a) a.begin(), a.end()
#define up(i, s, t) for (int i = s; i <= t; i++)
#define dw(i, s, t) for (int i = s; i >= t; i--)
const int N = 1e5 + 5;
int n, res, L, W, a[N];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> L >> W;
up(i, 1, n) cin >> a[i];
a[0] = -W, a[++n] = L;
up(i, 1, n) {
int t = max(0ll, a[i] - a[i - 1] - W);
res += (t + W - 1) / W;
}
cout << res << '\n';
return 0;
}
T2 [ABC153E] Crested Ibis vs Monster
完全背包板子,不讲。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int, int>
#define VI vector<int>
#define sz(a) a.size()
#define all(a) a.begin(), a.end()
#define up(i, s, t) for (int i = s; i <= t; i++)
#define dw(i, s, t) for (int i = s; i >= t; i--)
const int M = 2e4 + 2, N = 1e3 + 2;
int m, n, a[N], b[N], f[M];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int mxa = 0;
cin >> m >> n;
up(i, 1, n) cin >> a[i] >> b[i], mxa = max(mxa, a[i]);
fill(f + 1, f + m + mxa + 1, 2e9);
up(i, 1, n) up(j, a[i], m + mxa)
f[j] = min(f[j], f[j - a[i]] + b[i]);
int res = 1e15;
up(i, m, m + mxa) res = min(res, f[i]);
cout << res << '\n';
return 0;
}
T3 [tessoku_book_ec B56] Palindrome Queries
两种解法。
解法一:
跑一遍马拉车,看看相同对称中心的最大回文半径是否大于等与询问字符串的半径即可判断。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int, int>
#define VI vector<int>
#define sz(a) a.size()
#define all(a) a.begin(), a.end()
#define up(i, s, t) for (int i = s; i <= t; i++)
#define dw(i, s, t) for (int i = s; i >= t; i--)
const int N = 2e5 + 10;
int n, q, rad[N];
char s[N];
void read() {
char c;
s[0] = '#';
while (cin >> c && c >= 'a' && c <= 'z') s[++n] = 'A', s[++n] = c;
cin.unget();
s[++n] = 'A';
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int mid = 0, r = 0, l;
cin >> n >> q;
n = 0, read();
// up(i, 1, n) cout << s[i];
// cout << '\n';
up(i, 1, n) {
int j = 2 * mid - i;
if (r < i) rad[i] = 1;
else rad[i] = min(rad[j], r - i + 1);
while (s[i - rad[i]] == s[i + rad[i]]) rad[i]++;
if (i + rad[i] - 1 > r) {
r = i + rad[i] - 1;
mid = i;
}
}
while (q-- && cin >> l >> r) {
l = l * 2, r = r * 2;
// cout << s[l] << ' ' << s[(l + r) / 2] << ' ' << s[r] << '\n';
int len = r - l + 1;
if (rad[(l + r) / 2] >= (len + 1) / 2) cout << "Yes\n";
else cout << "No\n";
}
return 0;
}
解法二:
跑两遍哈希,判断从前面跑是否等于从后面跑的即可判断是否是回文串。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define VI vector<int>
#define sz(a) (int)a.size()
#define all(a) begin(a), end(a)
#define up(i, s, t) for (int i = s; i <= t; i++)
#define dw(i, s, t) for (int i = s; i >= t; i--)
const int N = 2e5 + 4, x = 123, MOD = 998244353;
int XP[N];
struct Hash {
VI H;
Hash(const string& ss) : H(ss.size() + 1) {
int n = ss.size();
dw(i, n - 1, 0) H[i] = (ss[i] - 'a' + 1 + H[i + 1] * x % MOD) % MOD;
}
int hash(size_t i, size_t j) {
return (H[i] - H[j + 1] * XP[j - i + 1] % MOD + MOD) % MOD;
}
};
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, Q, l, r;
string s, t;
XP[0] = 1;
up(i, 1, N - 1) XP[i] = XP[i - 1] * x % MOD;
cin >> n >> Q >> s, t = s, reverse(all(t));
Hash h1(s), h2(t);
while (Q-- && cin >> l >> r)
puts(h1.hash(l - 1, r - 1) == h2.hash(n - r, n - l) ? "Yes" : "No");
return 0;
}
T4 [ABC271C] Manga
直接模拟。若有书本
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int n, x, cost, ans;
set<int> s;
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> x;
s.insert(x);
}
for (int i = 1; ; i++) {
if (s.count(i)) cost += 1;
else cost += 2;
if (cost > n) break;
ans = i;
}
cout << ans;
return 0;
}
T5 [tessoku_book_fo C17] Strange Data Structure?
把它剖成两个序列,前面一半,后面一半,插入中间就可以直接插到前面的末尾,然后维护一下即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int Q, n = 0;
string x, op;
list<string> q0, q1;
for (cin >> Q; Q-- && cin >> op;) {
if (op == "A" && cin >> x) n++, q1.push_back(x);
else if (op == "B" && cin >> x) n++, q0.push_back(x);
else if (op == "C") q0.pop_front(), n--;
else cout << q0.front() << '\n';
if (q1.size() > n / 2) q0.push_back(q1.front()), q1.pop_front();
if (q0.size() > (n + 1) / 2) q1.push_front(q0.back()), q0.pop_back();
}
return 0;
}
T6 [USACO20FEB] Timeline G
直接跑拓扑排序再计算即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int, int>
#define VI vector<int>
#define sz(a) a.size()
#define all(a) a.begin(), a.end()
#define up(i, s, t) for (int i = s; i <= t; i++)
#define dw(i, s, t) for (int i = s; i >= t; i--)
const int N = 1e5 + 2;
int n, m, c, s[N], in[N];
vector<PII> g[N];
void topsort() {
queue<int> q;
up(i, 1, n) if (!in[i]) q.push(i);
while (q.size()) {
int u = q.front(); q.pop();
for (auto [v, w] : g[u]) {
in[v]--;
s[v] = max(s[v], s[u] + w); // 取最值
if (!in[v]) q.push(v);
}
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m >> c;
up(i, 1, n) cin >> s[i];
up(i, 1, c) {
int u, v, w;
cin >> u >> v >> w;
g[u].push_back({v, w});
in[v]++;
}
topsort();
up(i, 1, n) cout << s[i] << '\n';
return 0;
}