题目提供了一个表达式: H(s)=−∑1np(xi)log2(p(xi)) 其中,s 表示一个 01 字符串,p(xi) 表示符号 xi 在字符串中的占比。那么简单化简一下这个式子,我们用 x 表示 s 中 0 的个数,用 y 表示 s 中 1 的个数,n 表示 s 的长度,因为是 01 字符串,有 n = x + y。 H(s)=−(nx2log2nx+ny2log2ny) 题目告诉你 n = 23333333 以及 H(s) 的值,求 x 和 y。
首先你要知道计算机一秒大概可以完成 1e8 次简单运算(这个运算挺简单了吧),那么很简单我们枚举 x 去拟合 H(s) 即可。
1 2
// 11027421 // 赛时用 python 跑的,不重写了。
C 题:冶炼金属
题意是有一种商品,花 x 元钱可以买 y 个该商品。给你多组这样的 x 和 y ,请你确认这个商品的价格区间。
如果给你一对 x 和 y ,那么它确定的价格区间就是 [⌊y+1x⌋+1,⌊yx⌋] ,然后取所有区间的并即可。
注意不是 [⌈y+1x⌉,⌊yx⌋] ,这里提供错误数据 24 3 ,正确价格区间为 [7, 8]。我一个队友 S 这了,我赛时也考虑了这个问题。
voidsolve(){ int n; cin >> n; for (int i = 0; i < n; i++) { int x; cin >> x; int tail = x % 10; // 计算末尾 int head; while (x) { head = x % 10; x /= 10; } // 计算首位 res[tail] = max(res[tail], res[head] + 1); // 状态转移方程 } int max_ = 0; for (int i = 0; i < 10; i++) { max_ = max(max_, res[i]); // 获取最长接龙序列 } cout << n - max_ << endl; }
// binary_search 二分查找 intbs(int x){ int l = 0, r = cnt_bb - 1; while (l <= r) { int mid = l + r >> 1; if (bb[mid] < x) { l = mid + 1; } else { r = mid - 1; } } return l; }
voidsolve(){ int k; cin >> k; string s; cin >> s; int n = s.size(); char a, b; cin >> a >> b; for (int i = 0; i < n; i++) { if (s[i] == a) { aa[cnt_aa++] = i; // 转储 c1 位置序列 } if (s[i] == b) { bb[cnt_bb++] = i; // 转储 c2 位置序列 } } int res = 0; for (int i = 0; i < cnt_aa; i++) { res += cnt_bb - bs(aa[i] + k - 1); // 记录有效贡献 } cout << res << endl; }
我不知道命题组怎么想的 n = 5e5 的数据给了 1s 的时间,后面的 I 题 n = 1e5 的数据给了 5s 的时间。如果使用 STL 优先队列,由于常数问题我测试了民间数据 TLE 了,听了别人的写法大多都是使用优先队列的。实测手写 堆 或 线段树 不会 TLE ,这样卡常?莫非是有更优秀的解法?评论区留言。(下面的代码使用手写堆的)
// 线性初始化堆 voidbuild(int n){ total = siz = n; for (int i = 0; i < siz; i++) { a2h[i] = i; h2a[i] = i; } for (int i = siz / 2 - 1; i >= 0; i--) // 必须自下而上 down(i); }
// 景区导游 #include<bits/stdc++.h> #define int int64_t #define endl '\n' usingnamespace std; constint MAX = 1e5+5; constint LOG = 20; constint INF = 0x3f3f3f3f3f3f3f3fll; constint MOD = 1e9+7;
// 建议直接去写板子,别看了
int lg2[MAX]; int depth[MAX]; int st[MAX][LOG]; int dis[MAX]; vector<pair<int, int>> edge[MAX];
voidload_lg2(){ lg2[0] = -1; for (int i = 1; i < MAX; i++) { lg2[i] = lg2[i / 2] + 1; } }
voidbuild(int x, int pre, int level){ depth[x] = level; st[x][0] = pre; for (int i = 1; i <= lg2[depth[x]]; i++) { st[x][i] = st[st[x][i-1]][i-1]; } for (pair<int, int> p : edge[x]) { int y = p.first, d = p.second; if (y == pre) continue; dis[y] = dis[x] + d; build(y, x, level + 1); } }
intlca(int x, int y){ if (depth[x] > depth[y]) swap(x, y); while (depth[x] < depth[y]) { y = st[y][lg2[depth[y]-depth[x]]]; } if (x == y) return x; for (int i = lg2[depth[x]]; i >= 0; i--) { if (st[x][i] != st[y][i]) { x = st[x][i]; y = st[y][i]; } } return st[x][0]; }
int a[MAX]; int rount[MAX];
voidsolve(){ int n, k; cin >> n >> k; for (int i = 1; i < n; i++) { int u, v, w; cin >> u >> v >> w; edge[u].push_back({v, w}); edge[v].push_back({u, w}); } dis[1] = 0; build(1, 1, 0); for (int i = 0; i < k; i++) { cin >> a[i]; } int tot = 0; for (int i = 1; i < k; i++) { int f = lca(a[i-1], a[i]); rount[i] = dis[a[i-1]] - dis[f] + dis[a[i]] - dis[f]; tot += rount[i]; } cout << tot - rount[1] << ' '; // 第一个 for (int i = 1; i < k - 1; i++) { int f = lca(a[i-1], a[i+1]); // 中间置换 cout << tot - rount[i] - rount[i+1] + dis[a[i-1]] - dis[f] + dis[a[i+1]] - dis[f] << ' '; } cout << tot - rount[k-1] << endl; // 最后一个 while (true) { int x, y; cin >> x >> y; cout << lca(x, y) << endl; } }
// 砍树 #include<bits/stdc++.h> #define int int64_t #define endl '\n' usingnamespace std; constint MAX = 1e5+5; constint LOG = 20; constint INF = 0x3f3f3f3f3f3f3f3fll; constint MOD = 1e9+7;
// 代码较长,建议从 solve 开始看
int lg2[MAX]; int depth[MAX]; int st[MAX][LOG]; // pre[i] 即为 st[i][0] int weight[MAX]; vector<pair<int, int>> edge[MAX]; // pre : suf, idx
voidload_lg2(){ lg2[0] = -1; for (int i = 1; i < MAX; i++) { lg2[i] = lg2[i / 2] + 1; } }
voidbuild(int x, int pre, int level){ depth[x] = level; st[x][0] = pre; for (int i = 1; i <= lg2[depth[x]]; i++) { st[x][i] = st[st[x][i-1]][i-1]; } for (pair<int, int> p : edge[x]) { int y = p.first; if (y == pre) continue; build(y, x, level + 1); } }
intlca(int x, int y){ if (depth[x] > depth[y]) swap(x, y); while (depth[x] < depth[y]) { y = st[y][lg2[depth[y]-depth[x]]]; } if (x == y) return x; for (int i = lg2[depth[x]]; i >= 0; i--) { if (st[x][i] != st[y][i]) { x = st[x][i]; y = st[y][i]; } } return st[x][0]; }
voiddfs(int x, int pre){ for (pair<int, int> p : edge[x]) { int y = p.first; if (y == pre) continue; dfs(y, x); weight[x] += weight[y]; } }
voidsolve(){ int n, m; cin >> n >> m; for (int i = 1; i < n; i++) { int u, v; cin >> u >> v; edge[u].push_back({v, i}); edge[v].push_back({u, i}); } build(1, 0, 0); // lca 初始化, 不能写 build(1, 1, 0) for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; int f = lca(u, v); // 记录差分 weight[u]++; weight[v]++; weight[f]--; weight[st[f][0]]--; } dfs(1, 0); // 输出 int res = -1; for (int x = 1; x <= n; x++) { if (weight[x] == m) { for (pair<int, int> p : edge[x]) { int y = p.first, idx = p.second; if (weight[y] == m) { res = max(res, idx); } } } } cout << res << endl; }