2025省选模拟5

news/2025/1/15 20:21:32/文章来源:https://www.cnblogs.com/ccxswl/p/18670522

2025省选模拟5

这场比较简单,T1 T2 赛后都是没调打完就过了。既然改完了,而且现在也不想写啥题那就还是补下题解吧。


T1 枇杷树

操作 \(m\le 300\),每次操作构成一颗新树。具体:用边权为 \(w\) 的边连接编号为 \(x\) 的树中的 \(u\) 号节点,编号为 \(y\) 的树中的 \(v\) 号节点。

询问每颗树中的点两两之间距离。


考虑把两颗树连起来的影响:

\[ans=w\times siz_x \times siz_y+f_{x,u}\times siz_y + f_{y,v}\times size_x \]

\(f_{k,u}\) 表示编号为 \(k\) 的树中所有点到 \(u\) 的距离和。

维护 \(f_{k,u}\):考虑 \(u\) 是在 \(x_k\) 中还是 \(y_k\) 中即可。具体:

\[f_{k,p}= \begin{cases} siz_{y_k}\times (w_k + dis_{x_k,u_k,p})+f_{y_k,v_k} & p\in T_{x_k} \\ siz_{x_k}\times (w_k+dis_{y_k,v_k,p})+f_{x_k,u_k} & p\in T_{x_y} \end{cases} \]

\(dis_{k,i,j}\) 表示 \(T_k\)\(i,j\) 两点间的距离。

维护 \(dis\):一样分类讨论即可。详细见代码。

点数很多记忆化就行了。

正确性:\(f,dis\) 的转移只有关键点有关,关键点数量级为 \(O(m)\)\(f\) 状态数 \(O(m^2)\)\(dis\) 状态数 \(O(m^3)\)。总复杂度 \(O(m^3)\)

实现优美,是这种做法的最优解。赛后一遍过样例,没调直接交就过了。

#include <bits/stdc++.h>
#include <bits/extc++.h>using namespace std;
using namespace __gnu_pbds;#define IL inline
#define vec vector
#define bg begin
#define eb emplace_back
#define emp emplace
#define fi first
#define se second
#define mkp make_pair
using ubt = long long;
using uubt = unsigned long long;
using dub = double;
using puu = pair<ubt, ubt>;template <typename T = int>
IL T _R() {T s = 0, w = 1;char c = getchar();while (!isdigit(c)) w = c == '-' ? -1 : 1, c = getchar();while (isdigit(c)) s = s * 10 + c - 48, c = getchar();return s * w;
}constexpr int mod = 1e9 + 7;
constexpr int N = 300;
constexpr int maxN = N + 3;int m;ubt siz[maxN];
struct FUNCTION {IL ubt operator [] (int i) { return siz[i] % mod; }
} sz;int x[maxN], y[maxN];
ubt u[maxN], v[maxN];
int w[maxN];
ubt J[maxN];ubt ans[maxN];#define hshtb gp_hash_table
struct Has { IL uubt operator () (const puu &A) const { return A.fi * 13331ull + A.se; } };
hshtb<puu, ubt, Has> dis[maxN];
hshtb<ubt, ubt> f[maxN];ubt D(int k, ubt i, ubt j) {if (i == j) return 0;if (i > j) swap(i, j);if (dis[k][mkp(i, j)]) return dis[k][mkp(i, j)];if (j < J[k]) return D(x[k], i, j);if (i >= J[k]) return D(y[k], i - J[k], j - J[k]);ubt res = w[k] + D(x[k], i, u[k]) + D(y[k], j - J[k], v[k] - J[k]);return dis[k][mkp(i, j)] = res % mod;
}
ubt F(int k, ubt p) {if (!k && !p) return 0;if (f[k][p]) return f[k][p];ubt res = 0;if (p < J[k]) {res = sz[y[k]] * (w[k] + D(x[k], u[k], p)) % mod + F(y[k], v[k] - J[k]);res += F(x[k], p);} else {res = sz[x[k]] * (w[k] + D(y[k], v[k] - J[k], p - J[k])) % mod + F(x[k], u[k]);res += F(y[k], p - J[k]);}return f[k][p] = res % mod;
}int main() {freopen("loquat.in", "r", stdin);freopen("loquat.out", "w", stdout);m = _R();siz[0] = 1;for (int i = 1; i <= m; i++) {auto x = _R(), y = _R();auto u = _R<ubt>(), v = _R<ubt>() + siz[x];auto w = _R();siz[i] = siz[x] + siz[y];J[i] = siz[x];ans[i] = w * sz[x] % mod * sz[y] % mod;ans[i] += F(x, u) * sz[y] % mod + F(y, v - J[i]) * sz[x] % mod;ans[i] += ans[x] + ans[y];ans[i] %= mod;printf("%lld\n", ans[i]);::x[i] = x, ::y[i] = y, ::u[i] = u, ::v[i] = v, ::w[i] = w;}
}

上古遗迹

\(n,m\le 1e5,h_i\le 1e9\)

\(i\) 列有 \(h_i\) 个正方形。每次询问给出 \(l,r\)\([l,r]\) 中的最大矩形面积。


\(l_i\) 表示最大的 \(j\) 使得 \(j<i \land h_j<h_i\)。等不等其实不怎么关心。 \(r_i\) 定义类似。

这部分可以单调栈,或者直接 dfs 配合 RMQ(ST 表)跑类似笛卡尔树的结构。

询问区间为 \([L,R]\)。分类讨论:

\(l_i\le L \land R \le r_i\)

  • 显:\(A=\min\{h_{L\dots R}\}\times (R-L+1)\)

\(L\le l_i \land r_i \le R\)

  • \(A=(r_i-l_i+1)\times h_i\),扫描线维护即可。

\(L\le l_i \land R < r_i\)

  • \(A = (R-l_i+1)\times h_i=h_i R+(-l_i+1)h_i\)

\(l_i<L\land r_i\le R\)

  • \(A = (r_i-L+1)\times h_i=-h_iL+(r_i+1)h_i\)

容易发现后两个是一次函数的形式,扫描线+李超线段树即可。

赛时分类讨论完了,好久没写李超线段树,没想到,还以为时单峰的,上了个线段树上三分。

精细实现,目前最优解。一遍码完,没调。

#include <bits/stdc++.h>using namespace std;#define IL inline
#define vec vector
#define bg begin
#define eb emplace_back
#define emp emplace
#define fi first
#define se second
#define mkp make_pair
using ubt = long long;
using uubt = unsigned long long;
using dub = double;
using pdd = pair<dub, dub>;IL int _R() {int x;scanf("%d", &x);return x;
}IL void ckx(auto &x, const auto &y) { (x < y) && (x = y); }constexpr dub inf = 1e18;constexpr int N = 2e5;
constexpr int maxN = N + 3;int n, h[maxN];struct ST {int st[20][maxN];IL int get(int i, int j) { return h[i] <= h[j] ? i : j; }IL void init() {for (int i = 1; i <= n; i++) st[0][i] = i;for (int t = 1; t <= 18; t++)for (int i = 1; i + (1 << t) - 1 <= n; i++)st[t][i] = get(st[t - 1][i], st[t - 1][i + (1 << (t - 1))]);}IL int ask(int l, int r) {int t = __lg(r - l + 1);return get(st[t][l], st[t][r - (1 << t) + 1]);}
} st;struct BIT {ubt t[maxN];IL void ins(int x, ubt v) {for (; x <= n; x += x & -x) ckx(t[x], v);}IL ubt ask(int x) {ubt res = 0;for (; x > 0; x -= x & -x) ckx(res, t[x]);return res;}
} bita;struct LC_Segtree {
#define ls (p << 1)
#define rs (p << 1 | 1)struct dat {int k;ubt b;dat() : b(-inf) {}dat(int k, ubt b) : k(k), b(b) {}} t[N * 4];IL ubt G(int x, const dat &A) { return (ubt)A.k * x + A.b; }void C(int L, int R, int k, ubt b, int p, int l, int r) {int mid = (l + r) >> 1;if (L <= l && r <= R) {if (G(mid, t[p]) < G(mid, {k, b})) swap(k, t[p].k), swap(b, t[p].b);if (G(l, t[p]) >= G(l, {k, b}) && G(r, t[p]) >= G(r, {k, b})) return;if (G(l, t[p]) < G(l, {k, b}))C(L, R, k, b, ls, l, mid);if (G(r, t[p]) < G(r, {k, b}))C(L, R, k, b, rs, mid + 1, r);return;}if (L <= mid)C(L, R, k, b, ls, l, mid);if (R > mid)C(L, R, k, b, rs, mid + 1, r);}void A(int K, int p, int l, int r, ubt &ans) {ckx(ans, G(K, t[p]));if (l == r) return;int mid = (l + r) >> 1;if (K <= mid) A(K, ls, l, mid, ans);else A(K, rs, mid + 1, r, ans);}IL void clear() { fill(&t[0], &t[N * 4], dat{0, (ubt)-inf}); }
#undef ls
#undef rs
} T;int tot;
struct node {int l, r, h;ubt s;
} a[maxN];void D(int l, int r) {int g = st.ask(l, r);a[++tot] = {l, r, h[g], (ubt)(r - l + 1) * h[g]};if (l < g) D(l, g - 1);if (g < r) D(g + 1, r);
}int m;
struct ques {int l, r, id;
} q[maxN];
ubt ans[maxN];int main() {freopen("relics.in", "r", stdin);freopen("relics.out", "w", stdout);n = _R(), m = _R();for (int i = 1; i <= n; i++) h[i] = _R();st.init();D(1, n);// assert(tot == n);for (int i = 1; i <= m; i++)q[i].l = _R(), q[i].r = _R(), q[i].id = i;for (int i = 1; i <= m; i++) {ubt H = h[st.ask(q[i].l, q[i].r)];ans[i] = H * (q[i].r - q[i].l + 1);}auto cmp1 = [&](const auto &A, const auto &B) {return A.l > B.l;};sort(a + 1, a + n + 1, cmp1);sort(q + 1, q + m + 1, cmp1);for (int i = 1, now = 1; i <= m; i++) {auto &[l, r, id] = q[i];while (now <= n && a[now].l >= l) {bita.ins(a[now].r, a[now].s);now++;}ckx(ans[id], bita.ask(r));}auto cmp2 = [&](const auto &A, const auto &B) {return A.l > B.l;};sort(a + 1, a + n + 1, cmp2);sort(q + 1, q + m + 1, cmp2);for (int i = 1, now = 1; i <= m; i++) {auto &[l, r, id] = q[i];while (now <= n && a[now].l >= l) {int k = a[now].h;ubt b = (ubt)(-a[now].l + 1) * a[now].h;T.C(a[now].l, a[now].r, k, b, 1, 1, n);now++;}T.A(r, 1, 1, n, ans[id]);}T.clear();auto cmp3 = [&](const auto &A, const auto &B) {return A.r < B.r;};sort(a + 1, a + n + 1, cmp3);sort(q + 1, q + m + 1, cmp3);for (int i = 1, now = 1; i <= m; i++) {auto &[l, r, id] = q[i];while (now <= n && a[now].r <= r) {int k = -a[now].h;ubt b = (ubt)(a[now].r + 1) * a[now].h;T.C(a[now].l, a[now].r, k, b, 1, 1, n);now++;}T.A(l, 1, 1, n, ans[id]);}for (int i = 1; i <= m; i++)printf("%lld\n", ans[i]);
}

T3 吞天得手

求字典序前 \(k\) 小的子序列的哈希值。


非常简单 DFS 即可,赛时想到正解,复杂度分析错了,拿了 70 分,不过是赛时最高分。

如果我们搜索了前 \(i\) 小的子序列了,那往它后面加一个数比改它之中的一个数字典序小。依次搜索它后面第 \(j\) 小的数即可。注意字典序相同的子序列应该同时搜,不然你就错了。

赛时想法是枚举后面加什么,然后用 vector + 二分找位置。“枚举后面加什么数”复杂度就是错的了。

正解是主席树找后缀第 \(k\) 小。

#include <bits/stdc++.h>using namespace std;#define IL inline
#define vec vector
#define bg begin
#define eb emplace_back
#define emp emplace
using ubt = long long;
using dub = double;template <typename T = int>
IL T _R() {T s = 0, w = 1;char c = getchar();while (!isdigit(c)) w = c == '-' ? -1 : 1, c = getchar();while (isdigit(c)) s = s * 10 + c - 48, c = getchar();return s * w;
}constexpr int mod = 998244353;
constexpr int N = 1e5;
constexpr int maxN = N + 3;int n, k, B;
int a[maxN];int pos[maxN], nt[maxN];int top[maxN], tot;
struct dat {int l, r, v;
} t[N * 30];
IL void upd(int p) { t[p].v = t[p].l ? t[t[p].l].v : t[t[p].r].v; }
void C(int K, int &p, int w, int l, int r) {p = ++tot;t[p] = t[w];if (l == r) return t[p].v = K, void();int mid = (l + r) >> 1;if (a[K] <= mid)C(K, t[p].l, t[w].l, l, mid);elseC(K, t[p].r, t[w].r, mid + 1, r);upd(p);
}
int Q(int L, int R, int p, int l, int r) {if (!p) return -1;if (L <= l && r <= R) return t[p].v;int mid = (l + r) >> 1, res = -1;if (L <= mid) res = Q(L, R, t[p].l, l, mid);if (R > mid && res == -1)res = Q(L, R, t[p].r, mid + 1, r);return res;
}void dfs(const multiset<int> &S, ubt H) {int lst = 0;multiset<int> T;while (true) {int tmp = Q(lst + 1, N, top[(*S.bg()) + 1], 1, N);if (tmp == -1) return;lst = a[tmp];ubt A = (H * B + lst) % mod;T.clear();for (auto &i : S) {tmp = Q(lst, lst, top[i + 1], 1, N);if (tmp == -1) break;while (tmp != -1) {T.emp(tmp);printf("%lld\n", A);if (!--k) exit(0);tmp = nt[tmp];}}dfs(T, A);}
}int main() {freopen("ttds.in", "r", stdin);freopen("ttds.out", "w", stdout);n = _R(), k = _R(), B = _R();for (int i = 1; i <= n; i++) a[i] = _R();memset(pos, -1, sizeof(pos));for (int i = n; i >= 1; i--) {nt[i] = exchange(pos[a[i]], i);C(i, top[i], top[i + 1], 1, N);}dfs({0}, 0);
}

感觉看完暴力也就理解这题了,所以把赛时暴力也放上了。

#include <bits/stdc++.h>using namespace std;#define IL inline
#define vec vector
#define eb emplace_back
#define bg begin
#define lb lower_bound
#define ub upper_bound
using ubt = long long;template <typename T = int>
IL T _R() {T s = 0, w = 1;char c = getchar();while (!isdigit(c)) w = c == '-' ? -1 : 1, c = getchar();while (isdigit(c)) s = s * 10 + c - 48, c = getchar();return s * w;
}constexpr int mod = 998244353;
constexpr int N = 1e5;
constexpr int maxN = N + 3;int n, k;
int B;int a[maxN];vec<int> Hs, pos[maxN];void dfs(const vec<int> &s, ubt H) {for (int &v : Hs) {vec<int> tmp;for (const int &i : s) {auto gps = ub(pos[v].bg(), pos[v].end(), i);for (auto it = gps; *it <= n; it++)tmp.eb(*it);}if (tmp.empty()) continue;ubt A = (H * B + v) % mod;for (int &i : tmp) {printf("%lld\n", A);if (!--k) exit(1);}dfs(tmp, A);}
}int main() {freopen("ttds.in", "r", stdin);freopen("ttds.out", "w", stdout);n = _R(), k = _R(), B = _R();for (int i = 2; i <= n; i++)pos[a[i] = _R()].eb(i), Hs.eb(a[i]);sort(Hs.bg(), Hs.end());Hs.resize(unique(Hs.bg(), Hs.end()) - Hs.bg());for (int &v : Hs) pos[v].eb(n + 2);dfs({1}, 0);
}

这场也太阳间了。有时间写题解是因为没过营。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/869026.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习入门之手写数字识别

模型定义 我们使用 CNN 和 MLP 来定义模型: import torch.nn as nnclass Model(nn.Module):def __init__(self):"""定义模型结构输入维度为 1 * 28 * 28 (C, H, W)"""super(Model, self).__init__()# 卷积层 1self.conv1 = nn.Sequential(# 二维…

省选构造专题

省选构造专题 The same permutation 首先打个表,发现在 \(1\le n\le 5\) 之内的是否有合法方案的情况为 √√√ 大了打不出来了。 考虑一下 \(4,5\) 连续有解,注意到一个偶数有解,则这个偶数 \(+1\) 也必定有解。 考虑以下构造方法即对于某一个交换,可以在它前后各添加一个…

自动化进程如何优化敏捷开发中的工作流

一、敏捷开发管理工具的现状 1.1 敏捷开发管理工具的基本功能 目前,敏捷开发管理工具的主要功能包括任务管理、进度跟踪、团队协作、资源分配、需求变更管理等。这些工具通常采用看板、任务板、甘特图、Burndown图等形式,帮助团队成员可视化地管理任务、跟踪项目进度、协调跨…

不知道前端代码哪里报错了?我有七种方式去监控它!

大家好,我是桃子,前端小菜鸟一枚,在日常工作中,有时候是不是不知道前端代码哪里报错了今天我给大家分享七中方法去监控它 我们先来说说前端中的错误类型有哪一些 错误类型 1、SyntaxError SyntaxError 是解析时发生语法错误,这个错误是捕获不到的,因为它是发生在构建阶段,…

web.config站内301永久重定向代码示例

注:此代码只适用于IIS服务器,如需要将123.asp重定向到123.html,请使用以下代码。 修改说明: 在web.config文件中添加301重定向规则,将123.asp重定向到123.html。<?xml version="1.0" encoding="UTF-8"?> <configuration><system.web…

请问云服务器需要开放哪些常用端口?

云服务器需要开放的端口与具体使用环境是有关系的,开放的端口越多,存在的安全隐患也就越大,所以开放端口越少越好。服务类型 端口 说明Web服务 80(HTTP), 443(HTTPS) 提供网站访问服务。FTP 21(文件管理) 提供文件传输服务。注:21端口可以关闭或修改。远程连接服务 3…

Audacity 3.7 (Linux, macOS, Windows) - 开源音频编辑器和录音工具

Audacity 3.7 (Linux, macOS, Windows) - 开源音频编辑器和录音工具Audacity 3.7 (Linux, macOS, Windows) - 开源音频编辑器和录音工具 Audacity is the worlds most popular audio editing and recording app 请访问原文链接:https://sysin.org/blog/audacity/ 查看最新版。…

CAP:Serverless + AI 让应用开发更简单

AI 已被广泛视为推动行业进步的关键力量,其在各行业的落地步伐加快。企业在构建 AI 应用开发过程中经常会面临 AI 技术门槛过高、试错周期过长、GPU 资源昂贵且弹性能力不足、缺乏配套工具、业务与模型的开发运维过于割裂、缺乏定制化能力等挑战,成为企业构建 AI 应用的『绊脚…

【运维自动化-作业平台】如何使用全局变量之密文类型?

密文类型的全局变量使用场景相对较少,使用方式也是直接引用即可,目前仅支持shell。一起来看看如何使用实操演示 1、新建作业时创建一个密文类型的全局变量app_secret2、添加一个执行脚本的步骤,脚本里打印下这个全局变量3、调试执行更多应用场景 上面这个示例是用最简单的ec…

微信多开防撤回、防撤回PC版 | WeChat4.0.1.21

点击上方蓝字关注我 前言 很多使用微信电脑版的朋友可能都会遇到一个问题,那就是微信电脑版不能同时登录多个账号。这对于那些需要在电脑上同时管理多个微信账号的人来说,确实很不方便。还有时候,别人撤回了他们发的消息,而我们可能就错过了那些重要的内容。这个版本可以同…

【PCI】PCIe高级错误上报能力AER(十二)

AER AER(Advanced Error Reporting)是一种用于检测和报告PCIe设备中发生的错误的机制,它允许PCIe设备检测到并报告各种类型的错误。错误类型包含Correctable Errors 和Uncorrectable errors两种,其中Uncorrectable errors下面又分为ERR_FATAL和ERR_NONFATAL。Correctable Err…

鸿蒙开发 - 自定义组件 和 组件通信的方法

自定义组件的基本结构 @Entry @Component struct MyComponent {build(){// ...} }build()函数build()函数用于描述组件的UI界面,自定义组件必须定义build()函数 build() {Column() {Text(测试)Button(点击)} }struct 关键字strcut 用来声明数据结构 struct + 自定组件名 + { .…