ABC
略
D
解题思路
如果对于每个点,我们知道了它被移除的时刻(无限大则说明不会被移除),我们就可以知道询问的点在给定时刻有没有消失。
在对所有的点按横坐标分类后,我们就可以知道最多有多少行点被移除:点数最少的那一列的点数。
对于能够被移除的点,假设它处在 \(x\) 层,则被该点被移除的时刻就是第 \(x\) 层被移除的时刻 \(t[x] = max(t[x - 1] + 1, max_{点 i 在 x 层}Y_i)\)。
CODE
void solve()
{int n = 0, w = 0;std::cin >> n >> w;// 按横坐标分类std::vector X(w + 1, std::vector<int>{});// 每个点在第几层std::vector idx(n, 0);for (int i = 0; i < n; i++) {int x = 0, y = 0;std::cin >> x >> y;idx[i] = X[x].size();X[x].push_back(y);}int mn = n;for (int i = 1; i <= w; i++) {mn = std::min(mn, int(X[i].size()));}std::vector lay(mn, 0);for (int i = 1; i <= w; i++) {for (int j = 0; j < mn; j++) {lay[j] = std::max(lay[j], X[i][j]);}}for (int i = 1; i < mn; i++) {lay[i] = std::max(lay[i - 1] + 1, lay[i]);}int q = 0;std::cin >> q;while (q--) {int T = 0, a = 0;std::cin >> T >> a;a--;std::cout << ((idx[a] < mn ? lay[idx[a]] : Inf) > T ? "Yes" : "No") << '\n';}return;
}
E
解题思路
对于长度为 \(3^n\) (\(n > 0\))的一段 01 串,如果我们知道了它三个长度为 \(3^{n - 1}\) 的子串的值和改变这个值所要改变的数量,我们就可以知道答案了。递归着去求就好了。
CODE
std::string s;
// 预处理出 3 的幂
std::vector p3(N + 1, 1);// 传入左端点和区间长度的次数
std::pair<int, int> dfs(int l, int n) {// 递归出口if (n == 0) {return { s[l] - '0', 1 };}std::vector son{ dfs(l, n - 1), dfs(l + p3[n - 1], n - 1), dfs(l + 2 * p3[n - 1], n - 1) };std::sort(son.begin(), son.end());int val = 0, cost = 0;if (son[0].first == son[2].first) {val = son[0].first;int sum = 0, mx = 0;for (int i = 0; i < 3; i++) {sum += son[i].second;mx = std::max(mx, son[i].second);}cost = sum - mx;}else {val = son[1].first;if (val == 0) {cost = std::min(son[0].second, son[1].second);}else {cost = std::min(son[1].second, son[2].second);}}return { val, cost };
}void solve()
{int n = 0;std::cin >> n;std::cin >> s;std::cout << dfs(0, n).second << '\n';
}
F
解题思路
先把三个序列都降序排列,定义三元组 \(<i,j,k>\) 的值为 \(V(i, j, k)\),那么我们就知道了最大值是 \(V(0, 0, 0)\)。由于是降序排列,所以有一个很重要的性质:
\[V(i + 1, j, k) \leq V(i, j, k) \And V(i, j + 1, k) \leq V(i, j, k) \And V(i, j, k + 1) \leq V(i, j, k)
\]
所以对于第 \(x\) 大的 \(<i, j, k>\),第 \(x + 1\) 大的一定是上面三个中的一个,所以我们就直接优先队列就好了。
下面用了哈希做了三元组和值的互换。
CODE
int n;
std::vector<i64> A(N + 5), B = A, C = A;i64 f(std::array<int, 3> p) {i64 w = 1ll;i64 res = 0;for (int i = 0; i < 3; i++) {res += w * p[i];w *= n;}return res;
}std::array<int, 3> g(i64 val) {std::array<int, 3> res;for (int i = 0; i < 3; i++) {res[i] = val % n;val /= n;}return res;
}std::priority_queue<std::pair<i64, i64>> q;
std::set<i64> vis;void add(std::array<int, 3> p) {i64 hp = f(p);if (p[0] < n && p[1] < n && p[2] < n && vis.count(hp) == 0) {q.push({ A[p[0]] * B[p[1]] + B[p[1]] * C[p[2]] + A[p[0]] * C[p[2]], hp });vis.insert(hp);}
}void solve()
{int k = 0;std::cin >> n >> k;for (int i = 0; i < n; i++) {std::cin >> A[i];}for (int i = 0; i < n; i++) {std::cin >> B[i];}for (int i = 0; i < n; i++) {std::cin >> C[i];}std::sort(A.begin(), A.begin() + n, std::greater<i64>());std::sort(B.begin(), B.begin() + n, std::greater<i64>());std::sort(C.begin(), C.begin() + n, std::greater<i64>());q.push({ A[0] * B[0] + B[0] * C[0] + C[0] * A[0], 0 });for (int i = 0; i < k; i++) {if (i == k - 1) {std::cout << q.top().first << '\n';break;}auto [x, y, z] = g(q.top().second);q.pop();add({ x + 1, y, z });add({ x, y + 1, z });add({ x, y, z + 1 });}
}