Codeforces 做题记录 2023-10-22
远古做题记录。大概是 22 年写的。
CF1858E1 Rollbacks (Easy Version)
Description
给定一个初始为空的数列 \(a\),你需要处理以下操作:
+ x
将数 \(x\) 添加至数列尾部。- k
删除数列结尾 \(k\) 个数。!
回滚上一次操作,这里只考虑+
和-
操作。?
查询数列中不同的数的数量。
\(q\) 次操作,\(1\leq q \leq 10^6\),其中 ?
询问数量不超过 \(10^5\)。保证 -
操作时数列中至少存在 \(k\) 个数。
Solution
由于不强制在线,考虑建出操作树,每个点表示一个状态,一个点到根的路径表示的一个时刻的数列。
对于插入操作,我们相当于在原树上加一个叶子。而对于删除操作,相当于跳 \(k\) 级祖先。
然后就是比较棘手的撤销操作,由于它只撤销 +
和 -
,考虑每进行一次 +
和 -
,就把它当前所在的点丢到一个栈中,撤销就弹栈就行了。
询问可以离线下来,一遍 \(\texttt{dfs}\) 处理所有询问,每次相当于加入或删除一个数,这个开一个桶记录每个数出现次数就行了。
Code
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
const int N = 1e6 + 5;
const int M = 20;
int m, tot;
int val[N], ans[N], fa[N][M];
int cnt[N], now;
vector<int> e[N], q;
stack<int> s;
void dfs (int u) {
if (++cnt[val[u]] == 1) ++now;
ans[u] = now;
for (auto v : e[u]) dfs(v);
if (!--cnt[val[u]]) --now;
}
int main () {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> m;
s.push(0);
for (char o; m--; ) {
cin >> o;
if (o == '+') {
++tot, cin >> val[tot];
e[fa[tot][0] = s.top()].push_back(tot);
s.push(tot);
for (int k = 1; k < M; ++k) {
fa[tot][k] = fa[fa[tot][k - 1]][k - 1];
}
}
else if (o == '-') {
int x; cin >> x;
int now = s.top();
for (int k = M - 1; ~k; --k) {
if (x & (1 << k)) {
now = fa[now][k];
}
}
s.push(now);
}
else if (o == '!') s.pop();
else q.push_back(s.top());
}
dfs(0);
for (auto i : q) {
cout << ans[i] - 1 << '\n';
}
return 0;
}
CF1858E2 Rollbacks (Hard Version)
Description
给定一个初始为空的数列 \(a\),你需要处理以下操作:
+ x
将数 \(x\) 添加至数列尾部。- k
删除数列结尾 \(k\) 个数。!
回滚上一次操作,这里只考虑+
和-
操作。?
查询数列中不同的数的数量。
\(q\) 次操作,\(1\leq q \leq 10^6\),其中 ?
询问数量不超过 \(10^5\)。保证 -
操作时数列中至少存在 \(k\) 个数。
数据强制在线。
Solution
由于强制在线,我们考虑将树拉成一个数组,相当于只维护当前的链,并配合数据结构解决问题。
可以直接维护题目中的数组,每次 +
操作将数组拉长,-
操作缩小数组长度,这个是好维护的。
然后对于撤销操作,还是考虑用栈记录每一次 +
和 -
操作,撤销时取出栈顶逆向还原即可。
查询由于强制在线不能一遍做完,所以我们可以给每种权值第一次出现的位置赋一个 \(1\) 的权值,丢到树状数组中查询。
具体地,我们对于每一个权值开一个 \(\texttt{std::set}\),每次 +
操作对于 \(\texttt{set}\) 和树状数组的变化量都是 \(O(1)\) 的,大力更新一下就好了。
Code
#include <iostream>
#include <stack>
#include <set>
using namespace std;
using Pr = pair<char, int>;
const int N = 1e6 + 5;
int q, l;
int c[N], a[N];
stack<Pr> s;
set<int> v[N];
void add (int x, int y) {
for (; x < N - 2; x += (x & -x)) {
c[x] += y;
}
}
int query (int x) {
int res = 0;
for (; x; x -= (x & -x)) {
res += c[x];
}
return res;
}
void insert (int p, int x) {
int t = (v[x].empty() ? 0 : *v[x].begin());
v[x].insert(p);
if (v[x].size() == 1) {
add(p, 1);
}
else if (*v[x].begin() == p) {
add(p, 1), add(t, -1);
}
}
void remove (int p, int x) {
v[x].erase(v[x].find(p));
int t = (v[x].empty() ? 0 : *v[x].begin());
if (v[x].empty()) {
add(p, -1);
}
else if (p < t) {
add(p, -1), add(t, 1);
}
}
int main () {
cin >> q;
for (char o; q--; ) {
cin >> o;
if (o == '+') {
int x; cin >> x;
s.push({'+', a[++l]});
if (a[l]) remove(l, a[l]);
insert(l, a[l] = x);
}
else if (o == '-') {
int x; cin >> x;
l -= x;
s.push({'-', x});
}
else if (o == '?') {
cout << query(l) << endl;
}
else {
Pr t = s.top(); s.pop();
if (t.first == '+') {
remove(l, a[l]);
if (a[l] = t.second) insert(l, a[l]);
--l;
}
else {
l += t.second;
}
}
}
return 0;
}
CF1854E Game Bundles
Description
给定一个正整数 \(m\le 10^{10}\),请你构造一个数组 \(a\),长度为 \(k\),满足 \(\forall 1\le i\le k\le 60,1\le a_i\le 60\),且恰好存在 \(m\) 个集合 \(S \subseteq \{1,2,\dots,k\}\),使得 \(\sum\limits_{i\in S}a_i=60\) 。
Solution
不难发现合法的 \(a\) 有很多,所以考虑随机化。
由于要求所有数的和恰好为 \(60\),那么一定不会同时使用两个 \(a_i > 30\) 的数,所以考虑对于 \(a_i \le 30\) 的部分随机化,然后用 \(a_i > 30\) 的部分将答案调整成恰好 \(m\)。
可以不断地在 \([1, 10]\) 中随机一个数丢到 \(a\) 的末尾,加入时做一遍 \(\texttt{DP}\),直到再加一个数答案就会超过 \(m\),我们猜测此时答案一定很接近 \(m\)。
然后考虑调整,设 \(f_i\) 为使用当前的数恰好拼出一个 \(i\) 的方案数,加入一个数 \(x(x > 30)\) 的贡献就是 \(f_{60 - x}\)。
再猜测 \(f_i\) 整体上是递增的,所以从小到大加入 \(> 30\) 的数是较优的,如果加入这个数后答案还是 \(\le m\) 就一直加就好了。
感性理解一下,\(f\) 基本是均匀分布的,所以从大到小选期望只会选 \(\log m\) 次,然后考虑 \(f_0 = 1\),所以如果答案 \(< m\) 可以不断放 \(60\),那么就说明一定有解,所以它是能过的。
Code
#include <iostream>
#include <random>
#include <chrono>
using namespace std;
using LL = long long;
const int N = 62;
int n, a[N];
LL m, f[N];
mt19937 R(chrono::steady_clock::now().time_since_epoch().count());
int rand (int l, int r) {
return uniform_int_distribution<int>(l, r)(R);
}
int main () {
cin >> m;
for (LL _m = m; true; ) {
m = _m;
fill(f, f + N, 0), f[0] = 1;
for (int i = 1; i <= 40; n = i++) {
a[i] = rand(1, 10);
if (f[60] + f[60 - a[i]] > m) break;
for (int j = 60; j >= a[i]; --j) {
f[j] += f[j - a[i]];
}
}
if ((m -= f[60]) < 0) continue;
for (int i = 31; i <= 60; ++i) {
while (n < 60 && m >= f[60 - i]) {
m -= f[60 - i];
a[++n] = i;
}
}
if (!m) {
cout << n << '\n';
for (int i = 1; i <= n; ++i) {
cout << a[i] << ' ';
}
cout << '\n';
return 0;
}
}
return 0;
}
CF1876C Autosynthesis
Description
给定一个序列 \(a_1, a_2, \ldots, a_n\),构造一个长度为 \(k\) 序列 \(b_1, b_2, \ldots, b_k\),其中 \(k\) 为任意正整数,使得:
- 在 \(a\) 序列中删除下标为 \(b_1, b_2, \ldots, b_k\) 的数后,\(a\) 与 \(b\) 两个序列完全相同。一个下标可以被删除多次,即序列 \(b\) 中的元素不一定两两不同。
\(1 \le n \le 4 \times 10^5, 1 \le a_i \le n\)。
Solution
发现如果一个值为 \(a_i\) 的数最终没被删掉,那么下标 \(i\) 至少被删了一次,然后如果一个下标 \(i\) 被删掉了,那么一定存在一个 \(j\) 使得 \(a_j = i\)。
所以考虑对于每个 \(i\),从 \(i\) 向 \(a_i\) 连边,然后用颜色 \(col_i\) 刻画一个点 \(i\) 是否被删了至少一次,\(col = 1\) 表示被删过至少一次,称为黑点,\(col = 0\) 表示没被删过,称为白点。
容易发现这样连成的图为外向基环树,并且图有如下性质:
- 任何一个白点都连向一个黑点。
- 任何一个黑点都被一个白点所指向。
考虑如何构造每个点的颜色,首先显然任意叶子节点都满足 \(col = 0\),然后可以用叶子节点的颜色往上推。
具体的,对于树上的一个点,如果它有一个儿子为白点,那么它一定是黑点,否则我们默认它是白点。
对于环上的点,部分已经被自己的儿子确定,为黑点,其余的可能为黑点,也可能为白点,观察什么情况下环上的点会不符合要求,发现如果环上有连续两个白点,那么就不合法。
所以我们破环成链,并把每一段连续的白点拿出来,把其中一半的点变成黑点,此时就不会出现白点指向白点的情况了。
最后,我们已经求出了每个点的颜色,那么所有的白点,也就是未被删除的点,就构成的所求的 \(b\) 数组。
关于本做法的正确性,考虑这种构造什么情况下会出现无解,发现只会出现在一个点为自环,其余若干(偶数)个点依次链接,形成一条长度为奇数的链,可以证明此时不存在解。否则按照上述的黑白染色一定能构造出一组合法解。
Code
#include <iostream>
#include <numeric>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
using LL = long long;
const int N = 2e5 + 5;
const int Mod = 998244353;
int n;
int a[N], d[N], col[N];
vector<int> t[N], e[N], ans;
queue<int> q;
bool vis[N];
int arr[N * 2], len;
void dfs (int u) {
if (vis[u]) return;
vis[u] = 1, arr[++len] = u;
dfs(a[u]);
}
int main () {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int T = 1;
for (int tt = 1; tt <= T; ++tt) {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i], ++d[a[i]];
t[a[i]].push_back(i);
e[i].push_back(a[i]);
}
for (int i = 1; i <= n; ++i) {
if (!d[i]) q.push(i);
}
for (; !q.empty(); q.pop()) {
int u = q.front(); vis[u] = 1;
col[a[u]] |= !col[u];
if (!(--d[a[u]])) q.push(a[u]);
}
for (int i = 1; i <= n; ++i) {
if (!vis[i]) {
len = 0, dfs(i);
bool fl = 0;
for (int j = 1; j <= len; ++j) {
fl |= col[arr[j]];
}
if (!fl) {
for (int j = 2; j <= len; j += 2) {
col[arr[j]] = 1;
}
}
else {
copy(arr + 1, arr + len + 1, arr + len + 1);
int la = 0;
for (int j = 1; j <= len * 2; ++j) {
if (col[arr[j]]) {
if (la > len) break;
if (la) {
for (int k = la + 2; k < j; k += 2) {
col[arr[k]] = 1;
}
}
la = j;
}
}
}
}
}
for (int i = 1; i <= n; ++i) {
bool fl = 0;
if (col[i]) {
for (auto v : t[i])
fl |= !col[v];
}
else {
ans.push_back(a[i]);
fl = col[a[i]];
}
if (!fl) {
cout << -1 << '\n';
return 0;
}
}
cout << ans.size() << '\n';
for (auto i : ans) {
cout << i << ' ';
}
cout << '\n';
}
return 0;
}
CF241B Friends
Description
给定 \(n\) 个整数 \(a_1, a_2, \cdots, a_n\),求前 \(m\) 大两两异或值的和。
\(1\leq n\leq 5\times 10 ^ 4\),\(0\leq m\leq \frac {n(n - 1)} 2\),\(0 \leq a_i \leq 10 ^ 9\)。答案对 \(10 ^ 9 + 7\) 取模。
Solution
本题是 P5283 [十二省联考 2019] 异或粽子 的加强版,沿用那题的套路,我们将 \(m \gets m \times 2\),这样就不用考虑 \(i < j\) 的限制了。
直接求前 \(m\) 大异或值的和是不好做的,可以先二分一个第 \(m\) 大值 \(v\),然后计算所有大于 \(v\) 的数对的异或和。
还是对原序列建出 \(\texttt{01}\) \(\texttt{Trie}\),那么计算异或和不小于 \(v\) 的数对个数可以在 \(\texttt{Trie}\) 上二分,对于每一个节点维护一个 \(siz\),走一条异或和为 \(0\) 的边时把异或和为 \(1\) 的儿子的 \(siz\) 加上即可。
第二部分比较难搞,可以对每一个点维护一个 \(cnt_{i, j}\) 表示第 \(i\) 个点的子树中,有多少个数第 \(j\) 位为 \(1\),那么还是每走一条异或和为 \(0\) 的边时就计算一个另一个儿子产生的贡献。
那么相当于我们拆出了 \(\texttt{Trie}\) 上的 \(O(\log w)\) 个点,原理类似线段树,对于每个点我们要计算它子树内所有数与一个数 \(x\) 产生的贡献,我们利用 \(cnt\) 数组,枚举每一位即可 \(O(\log w)\) 计算。
两部分时间复杂度均为 \(O(n \log^2 w)\),注意空间复杂度也为 \(O(n \log^2 w)\),而空间限制为 \(\text{256 MB}\),无法通过,由于 \(n \le 5 \times 10^4\),对于 \(cnt\) 数组我们可以用 \(\texttt{unsigned}\) \(\texttt{short}\) 类型存储,这样它就能过了。
Code
#include <iostream>
using namespace std;
using LL = long long;
const int N = 5e4 + 5;
const int M = 30, T = N * M;
const int Mod = 1e9 + 7, Inv = (Mod + 1) / 2;
struct trie {
int tot;
unsigned short siz[T], cnt[T][M];
int ch[T][2];
void insert (int x) {
for (int k = 0, i = M - 1; ~i; --i) {
int w = (x >> i) & 1;
if (!ch[k][w]) ch[k][w] = ++tot;
k = ch[k][w];
for (int j = 0; j < M; ++j) {
cnt[k][j] += (x >> j) & 1;
}
++siz[k];
}
}
int rank (int x, int v) {
int res = 0, k = 0;
for (int i = M - 1; ~i; --i) {
int w = (x >> i) & 1, dir = (v >> i) & 1;
int lc = ch[k][w], rc = ch[k][w ^ 1];
if (dir) {
k = rc;
}
else {
res += siz[rc];
k = lc;
}
if (!k) return res;
}
return res + siz[k];
}
LL query (int x, int v) {
auto calc = [&](int k) -> LL {
LL ret = 0;
for (int i = M - 1; ~i; --i) {
int w = (x >> i) & 1, c = !w ? cnt[k][i] : siz[k] - cnt[k][i];
ret += 1ll * (1 << i) * c;
}
return ret;
};
int k = 0;
LL res = 0;
for (int i = M - 1; ~i; --i) {
int w = (x >> i) & 1, dir = (v >> i) & 1;
int lc = ch[k][w], rc = ch[k][w ^ 1];
if (dir) {
k = rc;
}
else {
res += calc(rc);
k = lc;
}
if (!k) return res;
}
return res + calc(k);
}
} t;
int n;
LL m;
int a[N];
int main () {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m, m <<= 1;
if (!m) {
cout << 0 << '\n';
return 0;
}
for (int i = 1; i <= n; ++i) {
cin >> a[i], t.insert(a[i]);
}
auto check = [&](int x) -> LL {
LL cnt = 0;
for (int i = 1; i <= n; ++i) {
cnt += t.rank(a[i], x);
}
return cnt;
};
int l = 0, r = (1 << M);
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid) <= m) {
r = mid - 1;
}
else {
l = mid + 1;
}
}
int ans = 1ll * (m - check(l)) * (l - 1);
for (int i = 1; i <= n; ++i) {
ans = (ans + t.query(a[i], l)) % Mod;
}
cout << (1ll * ans * Inv) % Mod << '\n';
return 0;
}
CF804D Expected diameter of a tree
Description
给定一片 \(n\) 个节点构成的森林,有 \(q\) 次询问,每个询问给出两个点 \(u, v\),问如果在这两个点所在的树中各随机选一个点连一条边,那么构成的新树期望直径是多少。询问之间相互独立。
\(n, q \le 10^5\)。
Solution
首先这种算两棵树连起来的直径的题都有一个经典套路,就是新树直径的两个端点是原来直径的 \(4\) 个端点两两匹配后距离最大的一对,知道这个这道题就好做了。
考虑加上一条边后的直径怎么算,假设我们选择两个点 \(u\) 和 \(v\) 连边,那么新树的直径就是 \(\max\{dl_u, dl_v, mx_u + mx_v + 1\}\),为了将这个式子变好看,我们令 \(d = \max\{dl_u, dl_v\} - 1\),那么它的贡献就变成了 \(\max\{d, mx_u + mx_v\}\),最后再把答案一起 \(+1\) 即可。
对于一棵树 \(i\),我们维护一个集合 \(S_i\) 表示这棵树中所有的 \(mx\) 值,那么计算 \(i\) 与 \(j\) 的贡献时我们可以枚举一棵树中的所有点,然后使用使用双指针计算。时间复杂度为 \(O(\max\{|S_i|, |S_j|\})\)。
考虑上述算法为什么无法通过。如果存在一个大小很大的树,不断询问它我们就会 TLE。发现树的个数与大小成反比,我们可以想到根号分治。
假设询问两颗树 \(i, j\),它们的大小分别为 \(siz_i, siz_j\)。
若 \(\max\{siz_i, siz_j\} \le \sqrt n\),那么直接使用上面的算法,单次询问时间复杂度不超过 \(O(\sqrt n)\)。
若 \(\max\{siz_i, siz_j\} > \sqrt n\),我们假设其中 \(siz_i > \sqrt n\),注意到这样的树不超过 \(\sqrt n\) 棵,对于每一棵树我们可以前缀和预处理 \(cnt_i, val_i\) 分别表示 \(mx_u \le i\) 的元素个数 / 权值和,这样单次查询是 \(O(1)\) 的,然后枚举其它树的所有节点预处理出所有包含这棵树的答案即可。
时间复杂度 \(O((n + q) \sqrt n)\),可以通过本题。
Code
#include <iostream>
#include <vector>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <map>
using namespace std;
using LL = long long;
using Pr = pair<int, int>;
const int N = 1e5 + 5;
const int M = 18;
int n, m, q, D, tot;
vector<int> e[N], vec[N];
map<Pr, double> ans;
int fa[N][M], dep[N], siz[N];
int rt[N], mx[N], id[N];
int dx[N], dy[N], dl[N];
int cnt[N];
LL val[N];
void dfs (int u, int r) {
fa[u][0] = r;
for (int k = 1; k < M; ++k) {
fa[u][k] = fa[fa[u][k - 1]][k - 1];
}
if (r) rt[u] = rt[r];
dep[u] = dep[r] + 1;
siz[u] = 1;
for (auto v : e[u]) {
if (v != r) {
dfs(v, u);
siz[u] += siz[v];
}
}
}
int lca (int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int k = M - 1; ~k; --k) {
if (dep[u] - dep[v] >= (1 << k)) {
u = fa[u][k];
}
}
if (u == v) return u;
for (int k = M - 1; ~k; --k) {
if (fa[u][k] != fa[v][k]) {
u = fa[u][k], v = fa[v][k];
}
}
return fa[u][0];
}
int dis (int u, int v) { return dep[u] + dep[v] - dep[lca(u, v)] * 2; }
int main () {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m >> q, D = sqrt(n);
for (int i = 1, u, v; i <= m; ++i) {
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
for (int i = 1; i <= n; ++i) {
if (!rt[i]) {
rt[i] = i, dfs(i, 0);
int mx;
auto dfs2 = [&](auto self, int u, int r, int &ext, int now = 0) -> void {
if (now > mx) ext = u, mx = now;
for (auto v : e[u]) {
if (v != r) {
self(self, v, u, ext, now + 1);
}
}
};
mx = -1, dfs2(dfs2, i, 0, dx[i], 0);
mx = -1, dfs2(dfs2, dx[i], 0, dy[i], 0);
dl[i] = dis(dx[i], dy[i]);
auto dfs3 = [&](auto self, int u, int r) -> void {
::mx[u] = max(dis(u, dx[i]), dis(u, dy[i]));
vec[i].push_back(::mx[u]);
for (auto v : e[u]) {
if (v != r) {
self(self, v, u);
}
}
};
dfs3(dfs3, i, 0);
sort(vec[i].begin(), vec[i].end());
}
}
for (int i = 1; i <= n; ++i) {
if (rt[i] != i || siz[i] <= D) continue;
fill(cnt, cnt + n + 1, 0);
fill(val, val + n + 1, 0);
for (auto j : vec[i]) {
++cnt[j], val[j] += j;
}
for (int j = 1; j <= n; ++j) {
cnt[j] += cnt[j - 1];
val[j] += val[j - 1];
}
for (int j = 1; j <= n; ++j) {
if (rt[j] != j) continue;
int d = max(dl[i], dl[j]) - 1;
LL ans = 1ll * siz[i] * siz[j];
for (auto k : vec[j]) {
int v = d - k, cnt = v < 0 ? 0 : ::cnt[v];
ans += 1ll * cnt * d + 1ll * (siz[i] - cnt) * k + (val[n] - val[max(v, 0)]);
}
::ans[{i, j}] = ans * 1.0 / (1ll * siz[i] * siz[j]);
}
}
for (int u, v; q--; ) {
cin >> u >> v;
u = rt[u], v = rt[v];
if (u == v) {
cout << -1 << '\n';
continue;
}
if (siz[u] < siz[v] || (siz[u] == siz[v] && u > v)) swap(u, v);
if (!ans.count({u, v})) {
int d = max(dl[u], dl[v]) - 1;
LL ans = 1ll * siz[u] * siz[v];
auto &vu = vec[u], &vv = vec[v];
int lu = vu.size(), lv = vv.size();
LL sum = 0;
for (int i = 0, j = lv; i < lu; ++i) {
while (j && vu[i] + vv[j - 1] > d) {
--j;
sum += vv[j];
}
ans += (sum + vu[i] * (lv - j)) + 1ll * j * d;
}
::ans[{u, v}] = ans * 1.0 / (siz[u] * siz[v]);
}
cout << fixed << setprecision(10) << ans[{u, v}] << '\n';
}
return 0;
}
Codeforces 做题记录 2023-10-22的更多相关文章
- 【做题记录】Codeforces做题记录
最近决定写一些CF Div.1的题,练习一下速度和代码能力. 暂定从中考后的Codeforces Round #572开始. 大部分比较简单的题直接把题解写在这里,不单独开文章了. Codeforce ...
- AtCoder,Codeforces做题记录
AGC024(5.20) 总结:猜结论,“可行即最优” B: 给定一个n的排列,每次可以将一个数移到开头或结尾,求变成1,2,...,n所需的最小步数. 找到一个最长的i,i+1,...,j满足在排列 ...
- UOJ 做题记录
UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...
- Sam做题记录
Sam做题记录 Hihocoder 后缀自动机二·重复旋律5 求一个串中本质不同的子串数 显然,答案是 \(\sum len[i]-len[fa[i]]\) Hihocoder 后缀自动机三·重复旋律 ...
- 退役IV次后做题记录
退役IV次后做题记录 我啥都不会了.... AGC023 D 如果所有的楼房都在\(S\)同一边可以直接得出答案. 否则考虑最左最右两边的票数,如果左边>=右边,那么最右边会投给左边,因为就算车 ...
- project euler做题记录
ProjectEuler_做题记录 简单记录一下. problem 441 The inverse summation of coprime couples 神仙题.考虑答案为: \[\begin{a ...
- 退役III次后做题记录(扯淡)
退役III次后做题记录(扯淡) CF607E Cross Sum 计算几何屎题 直接二分一下,算出每条线的位置然后算 注意相对位置这个不能先搞出坐标,直接算角度就行了,不然会卡精度/px flag:计 ...
- 退役II次后做题记录
退役II次后做题记录 感觉没啥好更的,咕. atcoder1219 历史研究 回滚莫队. [六省联考2017]组合数问题 我是傻逼 按照组合意义等价于\(nk\)个物品,选的物品\(\mod k\) ...
- BJOI做题记录
BJOI做题记录 终于想起还要做一下历年省选题了2333 然而咕了的还是比做了的多2333 LOJ #2178. 「BJOI2017」机动训练 咕了. LOJ #2179. 「BJOI2017」树的难 ...
- FJOI2017前做题记录
FJOI2017前做题记录 2017-04-15 [ZJOI2017] 树状数组 问题转化后,变成区间随机将一个数异或一,询问两个位置的值相等的概率.(注意特判询问有一个区间的左端点为1的情况,因为题 ...
随机推荐
- 【IDEA】DEBUG调试问题
不要将断点打在方法的声明上: 会有一个菱形标志,在标记之后运行DEBUG模式会跑不起来 查看所有的断点标记: 在这里直接找到所有标记位置,弄掉就会跑起来了
- 使用AI技术(单张图片或文字)生产3D模型 —— Ai生成3D模型的时代来了
地址: https://www.bilibili.com/video/BV1A2421P7pH/ 视频用到的工具voxcraft体验地址:https://voxcraft.ai/
- VScode调试C++工程
相关: Linux环境下配置vscode的C/C++编译环境 本文主要参考: https://zhuanlan.zhihu.com/p/385276301 ====================== ...
- cloudpickle —— Python分布式序列化的专用模块
给出cloudpickle的GitHub地址: https://github.com/cloudpipe/cloudpickle =================================== ...
- Java设计模式之单例模式 通俗易懂 超详细 【内含案例】
单例模式 推荐 Java 常见面试题 什么是单例模式 ? 确保程序中一个类只能被实例化一次,实现这种功能就叫单例模式 单例模式的好处是什么 ? 方便控制对象 节省资源减少浪费 怎么实现单例模式 ? 构 ...
- rk3568 | 瑞芯微平台GPIO引脚驱动编写
最近在玩瑞芯微平台的产品,移植了几个设备的驱动,遇到了一些问题,总结后发现大部分问题都出在了GPIO配置的问题上,写下本篇文章,用来分享一下调试的心得. 有喜欢瑞芯微的朋友,可以加我好友,拉你进群,一 ...
- AWS EC2 实例类型命名规则
AWS EC2(Elastic Compute Cloud)实例类型的命名规则反映了实例的性能特征.用途和硬件配置.这些实例类型的名称由几个组件构成,每个组件都提供了关于该实例类型特定方面的信息.理解 ...
- Android Studio 项目已经sync完成,但是在布局中显示:Design editor is unavaliable until after a sunncessful project sync
原因:在drawable文件夹中新增了一个png图标 解决:同步在drawable-v24文件中复制一份即可
- nacos 注册服务正常,服务列表内没有服务
解决办法: 在nacos里 创建 注册的 命名空间 , 然后再看服务列表 就会有对应命名空间的数据了
- 利用CSS 实现环形百分比进度展示
先看效果图: UI设计了这样的效果,已读人数占总人数的百分比,环形展示. 这里可以用echarts图表,也可以用css实现,因为我是在小程序环境下,考虑到包大小体积,采用了css实现. 核心就是一行代 ...