C. Flapping Takahashi
维护当前时刻 \(t\) 可达的高度区间 \([\text{lh}, \text{rh}]\) 。从时刻 \(t_{i-1}\) 到 \(t_i\) 区间扩散为 \([\text{lh}-\Delta t, \text{rh} + \Delta t]\) 。 然后对区间 \([l, u]\) 取交集。
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
void solve() {
int n, h;
cin >> n >> h;
int now = 0, lh = h, rh = h;
bool ans = true;
rep(i, n) {
int t, l, u;
cin >> t >> l >> u;
lh -= t-now; rh += t-now;
now = t;
lh = max(lh, l);
rh = min(rh, u);
if (lh > rh) ans = false;
}
if (ans) puts("Yes");
else puts("No");
}
int main() {
int t;
cin >> t;
while (t--) solve();
return 0;
}
D. Clouds
二维差分
显然只有被 \(1\) 朵云覆盖的格子才会影响答案
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
const int M = 2000;
int sky[M+1][M+1];
int one[M+1][M+1];
struct Cloud { int u, d, l, r; };
int main() {
int n;
cin >> n;
vector<Cloud> clouds;
rep(i, n) {
int u, d, l, r;
cin >> u >> d >> l >> r;
--u; --l;
sky[u][l]++;
sky[u][r]--;
sky[d][l]--;
sky[d][r]++;
clouds.emplace_back(u, d, l, r);
}
rep(i, M)rep(j, M) sky[i+1][j] += sky[i][j];
rep(i, M)rep(j, M) sky[i][j+1] += sky[i][j];
rep(i, M)rep(j, M) one[i+1][j+1] = sky[i][j]==1;
rep(i, M)rep(j, M+1) one[i+1][j] += one[i][j];
rep(i, M+1)rep(j, M) one[i][j+1] += one[i][j];
int base = 0;
rep(i, M)rep(j, M) if (sky[i][j] == 0) base++;
rep(i, n) {
auto [u, d, l, r] = clouds[i];
int dif = one[d][r] - one[d][l] - one[u][r] + one[u][l];
int ans = base + dif;
cout << ans << '\n';
}
return 0;
}
E. Distribute Bunnies
一种做法是二分图最大匹配
另一种做法是单独考虑每个无向图连通分量,为其定向:
- 边数 \(<\) 点数,树
- 边数 \(=\) 点数,基环树
- 边数 \(>\) 点数,把重边删掉就是等于的情况
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using P = pair<int, int>;
// Coodinate Compression
template<typename T=int>
struct CC {
bool initialized;
vector<T> xs;
CC(): initialized(false) {}
void add(T x) { xs.push_back(x);}
void init() {
sort(xs.begin(), xs.end());
xs.erase(unique(xs.begin(),xs.end()),xs.end());
initialized = true;
}
int operator()(T x) {
if (!initialized) init();
return upper_bound(xs.begin(), xs.end(), x) - xs.begin() - 1;
}
T operator[](int i) {
if (!initialized) init();
return xs[i];
}
int size() {
if (!initialized) init();
return xs.size();
}
};
int main() {
int m;
cin >> m;
vector<P> bunnies;
CC cc;
rep(i, m) {
int x, r;
cin >> x >> r;
bunnies.emplace_back(x-r, x+r);
cc.add(x-r); cc.add(x+r);
}
int n = cc.size();
vector<vector<int>> to(n);
rep(i, m) {
auto [a, b] = bunnies[i];
a = cc(a); b = cc(b);
to[a].push_back(b);
to[b].push_back(a);
}
int ans = 0;
vector<bool> used(n);
rep(i, n) if (!used[i]) {
int edge = 0, vertex = 0;
auto dfs = [&](auto& f, int v) -> void {
if (used[v]) return;
vertex++; edge += to[v].size();
used[v] = true;
for (int u : to[v]) f(f, u);
};
dfs(dfs, i);
edge /= 2;
ans += min(vertex, edge);
}
cout << ans << '\n';
return 0;
}
F. Concat (2nd)
按 \(S_i + S_j < S_j + S_i\) 排序
显然直接排显然超时
有两种优化方法:
- 先 \(\text{shuffle}\) 一遍再排
- 用 \(z\) 算法优化比较函数
代码实现1
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
void solve() {
int n;
cin >> n;
vector<string> s(n);
rep(i, n) cin >> s[i];
random_shuffle(s.begin(), s.end());
sort(s.begin(), s.end(), [&](const string& a, const string& b) {
return a+b < b+a;
});
auto cat = [&]() {
string res;
for (string& t : s) res += t;
return res;
};
rep(i, n-1) {
if (s[i]+s[i+1] == s[i+1]+s[i]) {
cout << cat() << '\n';
return;
}
}
swap(s[n-2], s[n-1]);
string ans = cat();
swap(s[n-2], s[n-1]);
if (n >= 3) {
swap(s[n-2], s[n-3]);
ans = min(ans, cat());
}
cout << ans << '\n';
}
int main() {
int t;
cin >> t;
while (t--) solve();
return 0;
}
代码实现2
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
void solve() {
int n;
cin >> n;
vector<string> s(n);
rep(i, n) cin >> s[i];
vector<vector<int>> z(n);
rep(i, n) z[i] = z_algorithm(s[i]);
auto comp = [&](int i, int j) {
int w = s[i].size();
if (s[i] != s[j].substr(0, w)) return (s[i] < s[j])?-1:1;
int r = s[j].size()-w;
if (r > 0 and z[j][w] < r) {
int k = z[j][w];
return (s[j][k] < s[j][w+k])?-1:1;
}
return (s[j].substr(r) < s[i])?-1:1;
};
vector<int> p(n);
rep(i, n) p[i] = i;
sort(p.begin(), p.end(), [&](int i, int j) {
if (s[i].size() > s[j].size()) return comp(j, i) == 1;
return comp(i, j) == -1;
});
{
auto old = s;
rep(i, n) s[i] = old[p[i]];
}
auto cat = [&]() {
string res;
for (string& t : s) res += t;
return res;
};
rep(i, n-1) {
if (s[i]+s[i+1] == s[i+1]+s[i]) {
cout << cat() << '\n';
return;
}
}
swap(s[n-2], s[n-1]);
string ans = cat();
swap(s[n-2], s[n-1]);
if (n >= 3) {
swap(s[n-2], s[n-3]);
ans = min(ans, cat());
}
cout << ans << '\n';
}
int main() {
int t;
cin >> t;
while (t--) solve();
return 0;
}
浙公网安备 33010602011771号