闲话 23.3.28
闲话
实验材料
今天中午放的是 cd 写的 映山红
本来想在博客里开骂的
想了想算了 没啥必要
还是说人和人的品味是互相独立的吧
但是常听隔着年代的歌
这情况大概只能是家长的灌输了吧
我不好评价了
约 4.5 小时后更新:
好 实验完了
果然写一些有争议话题会引发讨论 以及随之而来的关注
这篇闲话在推流前就拿到了 5-6 倍于平常的阅览
我记得之前有人在夏征写了当时争议挺大的新分级系统
然后拿了第一名
似乎这被称作“抖机灵”的样子
模拟赛
翻了 但是完全没翻!
T1
贪心构造。
我们先把每个点和他对应区间的最小值和最大值连边,过程中并查集维护连通性。然后对每个点扫区间,有能加的边就加上。可以反证法证明正确性?
总时间复杂度 \(O(n^2)\)。
code
#include <bits/stdc++.h>
using namespace std;
using ll = long long; using pii = pair<int, int>; using vi = vector<int>; using vp = vector<pii>;
#define rep(i,s,t) for (register int i = (s), i##END = (t) + 1; i < i##END; ++ i)
#define pre(i,s,t) for (register int i = (s), i##END = (t) - 1; i > i##END; -- i)
#define iot ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define file(fl) freopen(#fl".in", "r", stdin), freopen(#fl".out", "w", stdout)
#define timer cerr << 1. * clock() / CLOCKS_PER_SEC << '\n'
#define eb emplace_back
const int N = 1e6 + 10;
int n; pii a[N]; vp ans;
int dsu[N];
int find(int u) { return u == dsu[u] ? u : dsu[u] = find(dsu[u]); }
void adde(int u, int v) {
if (find(u) == find(v)) return;
if (u > v) swap(u, v);
ans.eb(u, v); dsu[find(u)] = find(v);
}
pii b[N];
inline bool check() {
rep(i,1,n) b[i].first = 1e9 + 7, b[i].second = -1;
for (auto [u, v] : ans) {
b[u].first = min(b[u].first, v);
b[u].second = max(b[u].second, v);
b[v].first = min(b[v].first, u);
b[v].second = max(b[v].second, u);
}
rep(i,1,n) if (b[i].first != a[i].first or b[i].second != a[i].second) return 0;
iota(dsu, dsu + n + 1, 0);
for (auto [u, v] : ans) {
dsu[find(u)] = find(v);
}
rep(i,1,n) if (find(i) != find(1)) return 0;
return ans.size() == n - 1;
}
signed main() {
cin >> n; iota(dsu, dsu + n + 1, 0);
rep(i,1,n) cin >> a[i].first >> a[i].second;
rep(i,1,n) adde(i, a[i].first), adde(i, a[i].second);
rep(i,1,n) {
if (a[i].first < a[i].second) {
rep(j, a[i].first, a[i].second) {
if (a[j].first <= i and i <= a[j].second)
adde(i, j);
}
}
}
if (!check()) cout << "-1" << '\n';
else for (auto [u, v] : ans) cout << u << ' ' << v << '\n';
}
T2
如果没有 key obs. 的话最多是能拿 92pts 吗?不知道有没有没看出来就切了的人啊!
没观察出来的话可以发现可以先把叶子找出来,并维护目前找到的子树区间以及根,然后直接向两边拓展区间、拼合区间。加一点随机化就可以 \(200\) 次操作过第三个包了。
key obs. 是 \(1\) 号节点肯定没有左儿子,所以从 \(1\) 号节点开始,每次向右拓展一个节点。
如果本节点没有右儿子,则这棵子树的范围和根已经确定了,直接连在 \(i + 1\) 上即可。
反之右子树的左端点确定,递归求解即可。
询问次数是 \(2n\) 的。
code
#include <bits/stdc++.h>
#include "interact.h"
using namespace std;
#define rep(i, s, t) for (register int i = (s), i##END = (t) + 1; i < i##END; ++i)
const int N = 100 + 10;
int lim, pre[N], mnv[N], mxv[N];
bool query_(int u, int l, int r) {
if (!u) {
if (l == 0 and r == lim) return true;
return false;
} return query(u, l, r);
}
void report_(int u, int v) {
if (u) {
report(u, v);
mnv[u] = min(mnv[u], mnv[v]);
mxv[u] = max(mxv[u], mxv[v]);
}
}
void solve(int u) {
if (!query_(u, mnv[u], mxv[u])) {
pre[u + 1] = u;
solve(u + 1);
} else {
int p = u;
while (p) {
if (!query_(pre[p], mnv[pre[p]], mxv[p])) {
report_(u + 1, p);
pre[u + 1] = pre[p];
solve(u + 1);
break;
} else {
report_(pre[p], p);
p = pre[p];
}
}
}
}
void guess(int n) {
lim = n;
mnv[0] = 0, mxv[0] = n;
rep(i,1,n) pre[i] = 0, mnv[i] = mxv[i] = i;
pre[1] = 0;
solve(1);
}
T3
咋搞的都有。场上的思路是按 \(2k + 1\) 分组,每 \(2k + 1\) 个定能组成一个最优子结构,剩下的节点按大小分,看是自成一组还是加入前面的一堆节点。但是好像比较难写。
所以写了个乱搞作法。首先承认这样一个结论:最终的节点度数一定只有 \(k\) 和 \(k + 1\)。这样我们就可以枚举度数为 \(k\) 的节点数量 \(x\),取 \(x\) 的最大值构造。
构造的话首先将前 \(x\) 个节点和后 \(x + 1\) 个节点分离,前 \(x\) 个节点和后 \(x + 1\) 个节点间需要连 \(kx\) 条边,每次取后 \(x + 1\) 个节点中度数最小的即可。
后 \(x + 1\) 个节点自己再连,拿个 set 维护一下重边即可。
取最小可以用堆,总时间复杂度不会证。
code
#include <bits/stdc++.h>
using namespace std;
using ll = long long; using pii = pair<int, int>; using vi = vector<int>; using vp = vector<pii>;
#define rep(i,s,t) for (register int i = (s), i##END = (t) + 1; i < i##END; ++ i)
#define pre(i,s,t) for (register int i = (s), i##END = (t) - 1; i > i##END; -- i)
#define iot ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define file(fl) freopen(#fl".in", "r", stdin), freopen(#fl".out", "w", stdout)
#define timer cerr << 1. * clock() / CLOCKS_PER_SEC << '\n'
#define eb emplace_back
const int N = 1e6 + 10;
int n, k, cnt;
struct el {
el(int id = 0, int val = 0, bool ck = 0)
: id(id), val(val), ck(ck) {}
int id, val; bool ck;
bool operator < (const el& b) const {
if (val != b.val) return val > b.val;
if (ck and !b.ck) return false;
return id > b.id;
}
};
priority_queue<el> que;
vector<el> vec;
struct hash_ {
template <typename T>
size_t operator() (T p) const {
if (p.first > p.second) swap(p.first, p.second);
return (size_t) p.first * 13331 + (size_t) p.second;
}
}; unordered_set<pii, hash_> st;
signed main() {
cin >> n >> k;
int x = -1;
rep(i,0,n) if (n - i >= k and (k + 1) * (n - i) >= i * k and !(((k + 1) * (n - i) + i * k) & 1)) x = i;
cout << x << endl;
cout << (x * k + (k + 1) * (n - x)) / 2 << '\n';
rep(i,x+1,n) que.emplace(i, 0, 0);
rep(i,1,x) rep(j,1,k) {
auto tmp = que.top(); que.pop();
cout << i << ' ' << tmp.id << '\n';
que.emplace(tmp.id, tmp.val + 1, 0);
}
while (que.top().val < k + 1) {
el t1 = que.top(), t2; que.pop();
vec.clear();
while (1) {
t2 = que.top(); que.pop();
if (st.count({t1.id, t2.id})) vec.eb(t2);
else { st.insert({t1.id, t2.id}); break; }
}
cout << t1.id << ' ' << t2.id << '\n';
for (auto v : vec) que.emplace(v);
que.emplace(t1.id, t1.val + 1, 1), que.emplace(t2.id, t2.val + 1, 1);
}
}
两道构造一道交互 就是这样的模拟赛
杂题
给定一个 \(n \times n\) 的正方形网格,用三种颜色染色,求有多少种染色方案使得至少一行或一列是同一种颜色。结果对 \(998244353\) 取模。
\(n\le 10^6\)。
看到这题就想到容斥。假设 \(f(i, j)\) 是至少 \(i\) 行 \(j\) 列是同一种颜色的方案数,答案就是
讨论一下 \(f\)。
注意到若 \(i, j\) 都 \(> 0\) 则同色的行列只有可能都是一种颜色。因此枚举颜色和随意涂色的位置可以得到 \(f(i, j) = 3\times 3^{(n - i)(n - j)}\)。
反之,我们只需要考虑行或列的情况,而 \(f(i, 0)\) 和 \(f(0, i)\) 同构,我们只需要讨论一种,这里讨论 \(f(i, 0)\)。\(i\) 行彼此无影响,并有 \(n - i\) 行随意涂色,枚举颜色和随意涂色的位置可以得到 \(f(i, 0) = f(0, i) = 3^i \times 3^{n(n - i)}\)。
由于需要容斥统计贡献,我们钦定 \(f(0, 0) = 0\),也就是这种情况没贡献。
注意到 \(f\) 存在两种不同的取值,我们不妨分开求解。
\(i, j\) 存在 \(0\) 时可以平凡 \(O(n)\) 计算,这部分的答案就是
\(i, j\) 都不是 \(0\) 时,答案就是
我们不妨枚举 \(k = i + j\),将式子写成卷积形式:
中间的一步写开就是 \(ij = \dbinom{i + j}{2} -\dbinom{i}{2} - \dbinom{j}{2}\)。
可以多项式乘法优化求解。总时间复杂度 \(O(n\log n)\)。
以下是博客签名,与正文无关。
请按如下方式引用此页:
本文作者 joke3579,原文链接:https://www.cnblogs.com/joke3579/p/chitchat230328.html。
遵循 CC BY-NC-SA 4.0 协议。
请读者尽量不要在评论区发布与博客内文完全无关的评论,视情况可能删除。