A. Election 2
模拟
代码实现
n, t, a = map(int, input().split())
x = n-t-a
if t+x > a and t < a+x: print('No')
else: print('Yes')
B. Vertical Writing
模拟
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n;
cin >> n;
vector<string> s(n);
rep(i, n) cin >> s[i];
int m = 0;
rep(i, n) m = max(m, (int)s[i].size());
vector<string> t(m, string(n, '*'));
rep(i, n)rep(j, s[i].size()) {
t[j][n-1-i] = s[i][j];
}
rep(i, m) {
while (t[i].back() == '*') t[i].pop_back();
cout << t[i] << '\n';
}
return 0;
}
C. Balls and Bag Query
可以开一个数组 cnt
来记录每个数 \(x\) 的个数,考虑 cnt[x]
加减 \(1\) 后对答案的影响
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int q;
cin >> q;
vector<int> cnt(1000001);
int ans = 0;
rep(qi, q) {
int type;
cin >> type;
if (type == 3) {
cout << ans << '\n';
}
else {
int x;
cin >> x;
if (type == 1) {
if (cnt[x] == 0) ans++;
cnt[x]++;
}
else {
cnt[x]--;
if (cnt[x] == 0) ans--;
}
}
}
return 0;
}
D. Cuboid Sum Query
三维前缀和,简单容斥一下即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int a[101][101][101];
int s[102][102][102];
int main() {
int n;
cin >> n;
rep(i, n)rep(j, n)rep(k, n) cin >> a[i][j][k];
rep(i, n)rep(j, n)rep(k, n) s[i+1][j+1][k+1] = a[i][j][k];
rep(i, n+1)rep(j, n+1)rep(k, n+1) s[i+1][j][k] += s[i][j][k];
rep(i, n+1)rep(j, n+1)rep(k, n+1) s[i][j+1][k] += s[i][j][k];
rep(i, n+1)rep(j, n+1)rep(k, n+1) s[i][j][k+1] += s[i][j][k];
int q;
cin >> q;
rep(qi, q) {
int lx, rx, ly, ry, lz, rz;
cin >> lx >> rx >> ly >> ry >> lz >> rz;
--lx; --ly; --lz;
auto sum_z = [&](int rx, int ry, int lz, int rz) {
return s[rx][ry][rz] - s[rx][ry][lz];
};
auto sum_yz = [&](int rx, int ly, int ry, int lz, int rz) {
return sum_z(rx, ry, lz, rz) - sum_z(rx, ly, lz, rz);
};
auto sum_xyz = [&](int lx, int rx, int ly, int ry, int lz, int rz) {
return sum_yz(rx, ly, ry, lz, rz) - sum_yz(lx, ly, ry, lz, rz);
};
int ans = sum_xyz(lx, rx, ly, ry, lz, rz);
cout << ans << '\n';
}
return 0;
}
E. Manhattan Multifocal Ellipse
\( \sum (|x - x_i| + |y-y_i|) = (\sum |x-x_i|) + (\sum |y-y_i|) \)
可以看出 \(x\) 和 \(y\) 彼此相互独立
由 \(D\) 和 \(x_i\) 的范围可以推出 \(|x| \leqslant 2 \times 10^6\)
记 \(a[x] = \sum |x-x_i|\),\(b[y] = \sum |y-y_i|\)
那么原问题就转化成了求有多少个二元组 \((i, j)\) 满足 \(a[i] + b[j] \leqslant D\),可以对 \(a\) 和 \(b\) 排序后用双指针来解决
另外,对于 \(a[x]\) 的预处理同样可以用双指针,考虑差分思想,比如从 \(0\) 移动到 \(1\),可以发现 \(0\) 左边的所有 \(x_i\) 会在前面到 \(0\) 的距离的基础上扩张一个单位,\(0\) 右边的所有 \(x_i\) 会在到 \(0\) 的距离的基础上缩短一个单位
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
const int M = 1e6;
vector<ll> f(vector<int> x) {
int n = x.size();
rep(i, n) x[i] += M*2;
ll s = 0;
rep(i, n) s += x[i];
vector<ll> res(M*4+1);
res[0] = s;
ranges::sort(x);
int k = 0;
for (int i = 1; i <= M*4; ++i) {
while (k < n and x[k] < i) ++k;
s -= n-k*2;
res[i] = s;
}
return res;
}
int main() {
int n, d;
cin >> n >> d;
vector<int> x(n), y(n);
rep(i, n) cin >> x[i] >> y[i];
auto a = f(x);
auto b = f(y);
ranges::sort(a);
ranges::sort(b);
ll ans = 0;
int j = b.size()-1;
rep(i, a.size()) {
while (j >= 0 and a[i]+b[j] > d) --j;
ans += j+1;
}
cout << ans << '\n';
return 0;
}
F. Maximum Composition
先确定 \(f\) 的顺序,\(f_j\) 可以排在 \(f_i\) 的前面当且仅当 \(f_i(f_j(x)) > f_j(f_i(x))\)
\(
\Leftrightarrow A_i(A_jx + B_j)+B_i > A_j(A_ix + B_i) + B_j
\)
\(
\Leftrightarrow A_iA_jx + A_iB_j + B_i > A_iA_jx + A_jB_i + B_j
\)
\(
\Leftrightarrow A_iB_j + B_i > A_jB_i +B_j
\)
\(
\Leftrightarrow (A_i-1)B_j > (A_j-1)B_i
\)
\(
\Leftrightarrow \frac{A_i-1}{B_i} > \frac{A_j-1}{B_j}
\)
接下来就可以考虑dp了
记 dp[i][k]
表示到 \(f_i'\) 为止已经选了 \(k\) 个时的最大值
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
struct F {
ll a, b;
F(ll a=0, ll b=0): a(a), b(b) {}
ll operator()(ll x) { return a*x+b; }
};
int main() {
int n, k;
cin >> n >> k;
vector<F> f(n);
rep(i, n) cin >> f[i].a >> f[i].b;
ranges::sort(f, [&](F f1, F f2) {
return f2(f1(0)) > f1(f2(0));
});
vector<ll> dp(k+1, 1);
rep(i, n) {
vector<ll> old(k+1, 1);
swap(dp, old);
rep(j, k+1) {
dp[j] = max(dp[j], old[j]);
if (j < k) dp[j+1] = max(dp[j+1], f[i](old[j]));
}
}
cout << dp[k] << '\n';
return 0;
}
G. XOR Neighbors
对于异或一般都可以按位考虑,所以首先要考虑在顶点上写 \(0\) 或 \(1\),使得它所有相邻顶点上的点权的异或和为 \(0\) 的方案。
根据条件,可以列出 \(n\) 个方程 \(Ax = 0\) 的方程组。为了构造出一个题目的合法解,每个数中至少应该处理出 \(2\) 位,另外由于右边都是 \(0\),所以不妨分别考虑令每个 \(x_i = 1\),然后用高斯消元法求出一组解,最后再将这些解按位组合起来即可。
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
struct Matrix {
using BS = bitset<61>;
int h, w;
vector<BS> d;
Matrix(int h, int w): h(h), w(w), d(h) {}
BS operator[](int i) const { return d[i]; }
BS& operator[](int i) { return d[i]; }
BS solve() {
int ni = 0;
rep(j, w-1) {
for (int i = ni; i < h; ++i) {
if (d[i][j]) { swap(d[i], d[ni]); break; }
}
if (!d[ni][j]) continue;
rep(i, h) if (ni != i and d[i][j]) d[i] ^= d[ni];
ni++;
if (ni == h) break;
}
BS no, res; no[w-1] = 1;
rep(i, h) {
int j = 0;
while (j < w-1 and !d[i][j]) ++j;
if (j == w-1) {
if (d[i][w-1]) return no;
continue;
}
res[j] = d[i][w-1];
}
return res;
}
};
int main() {
int n, m;
cin >> n >> m;
Matrix d(n+1, n+1);
rep(i, m) {
int u, v;
cin >> u >> v;
--u; --v;
d[u][v] = 1;
d[v][u] = 1;
}
vector<ll> ans(n);
rep(i, n) {
Matrix = d;
nd[n][i] = 1; nd[n][n] = 1;
auto sol = nd.solve();
if (sol[n]) {
puts("No");
return 0;
}
rep(j, n) if (sol[j]) ans[j] |= 1ll<<i;
}
puts("Yes");
rep(i, n) cout << ans[i] << ' ';
return 0;
}