AtCoder Regular Contest 194 (Div. 2)

news/2025/3/10 12:16:59/文章来源:https://www.cnblogs.com/definieren/p/18762371

ARC194A Operations on a Stack

发现一定是删掉若干段偶数长度的不选,直接 DP 即可做到线性。

void slv() {int n = Read<int>();vector<int> A(n);for (int i = 0; i < n; i ++) {Read(A[i]);}vector<array<ll, 3>> f(n);f[0][2] = A[0], f[0][1] = 0, f[0][0] = -inf;for (int i = 1; i < n; i ++) {f[i][2] = A[i] + max(f[i - 1][0], f[i - 1][2]);f[i][1] = max(f[i - 1][0], f[i - 1][2]);f[i][0] = f[i - 1][1];}Write(max(f[n - 1][0], f[n - 1][2]), '\n');return;
}

ARC194B Minimum Cost Sort

考虑下界。

对于每个数 \(i\),如果存在逆序对 \((j, i)\),那么就至少需要和 \(j\) 交换一次.,那么下界就是一个等差数列求和。

\(c_i\) 表示 \(i\) 位置的逆序对个数,不难得到下界为:

\[\sum_{1 \le i \le N} \frac{c_i(2i - c_i - 1)}{2} \]

用一种你喜欢的方式求出逆序对后计算即可。

void slv() {int n = Read<int>();ll ans = 0; Fenwick<int> tr(n + 1);for (int i = 1; i <= n; i ++) {int x = Read<int>();int s = tr.Query(n - x + 1);ans += 1LL * ((i - s) + (i - 1)) * ((i - 1) - (i - s) + 1) / 2;tr.Update(n - x + 1, 1);}Write(ans, '\n');return;
}

ARC194C Cost to Flip

一定是先把一些 \(1\) 变成 \(0\),然后再把 \(0\) 变成 \(1\)

其中第一步操作的一定是所有的 \(A_i = 1, B_i = 0\) 位置和一部分 \(A_i = B_i = 1\) 的位置,第二步操作的一定是所有的 \(A_i = 0, B_i = 1\) 的位置和在第一步中操作过的 \(A_i = B_i = 1\) 的位置。

通过进一步的观察,发现对于 \(A_i = B_i = 1\) 的位置,我们只会改按 \(C_i\) 从大到小排序后的一段前缀。

然后就枚举这段前缀随便统计一下答案啥的,反正细节很多,烦。

void slv() {int n = Read<int>();vector<int> A(n), B(n), C(n);for (int i = 0; i < n; i ++) {Read(A[i]);}for (int i = 0; i < n; i ++) {Read(B[i]);}for (int i = 0; i < n; i ++) {Read(C[i]);}vector<int> pA, pB, pC;for (int i = 0; i < n; i ++) {if (A[i] == 1 && B[i] == 0) {pA.emplace_back(i);} else if (A[i] == 0 && B[i] == 1) {pB.emplace_back(i);} else if (A[i] == 1 && B[i] == 1) {pC.emplace_back(i);}}sort(pA.begin(), pA.end(), [&](int i, int j) { return C[i] > C[j]; });sort(pB.begin(), pB.end(), [&](int i, int j) { return C[i] < C[j]; });sort(pC.begin(), pC.end(), [&](int i, int j) { return C[i] > C[j]; });const int nA = pA.size(), nB = pB.size(), nC = pC.size();vector<ll> f(1 + nC);{ll s = 0;for (int i = 0; i < n; i ++)if (A[i] == 1) s += C[i];for (int i = 0; i < nA; i ++) {s -= C[pA[i]], f[0] += s;}s = 0;for (int i = 0; i < n; i ++)if (A[i] == 1) s += C[i];for (int i = 1, j = 0; i <= nC; i ++) {while (j < nA && C[pA[j]] > C[pC[i - 1]]) s -= C[pA[j ++]];s -= C[pC[i - 1]];f[i] = f[i - 1] - 1LL * C[pC[i - 1]] * (nA - j) + s;}};vector<ll> g(1 + nC);{ll s = 0;for (int i = 0; i < n; i ++)if (B[i] == 1 && A[i] == 1) s += C[i];for (int i = 0; i < nB; i ++) {s += C[pB[i]], g[0] += s;}s = 0;for (int i = 0; i < n; i ++)if (B[i] == 1) s += C[i];for (int i = 1, j = nB - 1; i <= nC; i ++) {while (j >= 0 && C[pB[j]] > C[pC[i - 1]]) s -= C[pB[j --]];g[i] = g[i - 1] + s - 1LL * C[pC[i - 1]] * (j + 1);s -= C[pC[i - 1]];}};ll ans = 1E18;for (int i = 0; i <= nC; i ++)cmin(ans, f[i] + g[i]);Write(ans, '\n');return;
}

ARC194D Reverse Brackets

建括号树,操作就是选一段连续的儿子区间,然后将 这段区间 和 其所有后代的儿子 reverse 一下。

同时还要对后代操作非常烦,但是可以通过对所有儿子操作一次变成 reverse 一段连续的儿子区间。

那么现在要做的就是每次可以 reverse 一段连续的儿子区间,问能生成多少棵本质不同的树。

考虑 DFS 计算答案,对于一个点,如果直接算儿子的方案数的乘积然后任意排列的话会算重。

进一步分析,发现 \(size\) 不同的子树是不互相影响的,\(size\) 相同的子树可以钦定必须是从左到右的顺序,这样就不会算重了。

暴力模拟上面的过程是 \(O(n^2)\) 的。

constexpr int N = 5e3 + 5;
char s[N];void slv() {int n; Read(n), Read(s + 1);vector<int> sum(n + 1);for (int i = 1; i <= n; i ++) {sum[i] = (s[i] == '(' ? 1 : -1);}partial_sum(sum.begin(), sum.end(), sum.begin());int cur = 0;map<vector<int>, int> id;id[vector<int>()] = 0;auto ID = [&](const vector<int> &v) {if (!id.count(v)) {id[v] = ++ cur;}return id[v];};auto Solve = [&](auto self, int L, int R) -> pair<int, mint> {if (L > R) {return {0, 1};}vector<pair<int, mint>> son;for (int l = L, r; l <= R; l = r + 1) {r = l;while (sum[++ r] != sum[l - 1]);son.emplace_back(self(self, l + 1, r - 1));}sort(son.begin(), son.end());const int n = son.size();mint ans = 1;for (int l = 0, r; l < n; l = r + 1) {r = l, ans *= son[l].sec;while (r + 1 < n && son[r + 1].fir == son[l].fir) {ans *= son[++ r].sec;}ans *= comb.C(r + 1, r - l + 1);}vector<int> hsh(n);for (int i = 0; i < n; i ++)hsh[i] = son[i].fir;return {ID(hsh), ans};};Write((int)Solve(Solve, 1, n).sec, '\n');return;
}

ARC194E Swap 0^X and 1^Y

对于一段连续的 \(1\),将它分成若干段 \(= X\)\(A\)\(< X\)\(1\)\(0\) 同理分成 \(B\)\(0\)

不难发现,如果我们允许 \(A\)\(1\)\(B\)\(0\)\(A\)\(B\) 之间的交换,那么这个和原问题是没有区别的,因为不会发生初始不同的 \(0 / 1\) 的连续段之间的拼接。

发现此时 \(0\) 限制住了 \(1\)\(A\) 的移动,\(1\) 限制住了 \(0\)\(B\) 的移动,所以直接把相邻 \(0\) 之间 \(1\) 的个数、相邻 \(0\) 之间 \(A\) 的个数,相邻 \(1\) 之间 \(B\) 的个数这三个东西看成特征值,特征值相等的序列一定能互相转化。

求出 \(S\)\(T\) 的特征值之后进行判定即可,时间复杂度线性。

constexpr int N = 5E5 + 5;
char s[N], t[N];void slv() {int N, X[2];Read(N, X[0], X[1]);vector<int> A(N), B(N);Read(s), Read(t);for (int i = 0; i < N; i ++) {A[i] = s[i] - '0';B[i] = t[i] - '0';}auto calc = [&](const vector<int> &a, int x, int y) {const int n = a.size();vector<int> ans; int cnt = 0;for (int i = 0; i < n; i ++) {if (a[i] == x) {++ cnt;} else if (a[i] == y) {ans.emplace_back(cnt);cnt = 0;}}ans.emplace_back(cnt);return ans;};auto trans = [&](const vector<int> &a) -> tuple<vi, vi, vi> {const int n = a.size();vector<int> b;for (int l = 0, r; l < n; l = r + 1) {r = l; int o = a[l];while (r + 1 < n && a[r + 1] == a[l]) {++ r;}int len = r - l + 1;while (len >= X[o]) {b.emplace_back(2 + o);len -= X[o];}while (len) {b.emplace_back(o);-- len;}}return {calc(b, 0, 1), calc(b, 0, 3), calc(b, 1, 2)};};Yes(trans(A) == trans(B));return;
}

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

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

相关文章

Hadoop集群安装

一.环境准备我使用的是virtualBox虚拟机,没有可以去官网下载 虚拟机镜像是ubuntu server22.04,官网地址[注意]我的主机系统就是linux,如果是windows需要自己下载一些终端连接的工具 二.安装 1.虚拟机准备直接finish,开始配置网卡。简单点说,桥接网络我们用来上网的,其次是h…

task1_2.c

include<stdio.h> int main() { printf(" 0 \n"); printf("\n"); printf("I I\n"); printf(" 0 \n"); printf("\n"); printf("I I\n"); return 0; }

No.44 ES6---Babel转码器(安装有点问题,用到再说)

一、Babel转码器Babel是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在老版本的浏览器执行。 这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持。 1.浏览器支持性查看https://caniuse.com/2.Babel 官网https://babeljs.io/3.转码示例原始…

kubesphere中查看argocd登陆密码

获取argocd密码PASSWORDkubectl get secret argocd-initial-admin-secret -nargocd -o jsonpath="{.data.password}"|base64 -d 登陆: admin/PASSWORD

rockchip sdk使用make menuconfig无法删除选项文字(MobaXterm)

问题:在使用make menuconfig编辑内核配置时,按退格键删除不了相关选项,如下图所示:解决办法: 1. 在全局设置部分,把这里的退格键发送^H取消勾选:2. 在开启一个新会话时,进行同样的设置:

线控转向控制系统SbW

线控转向控制系统是一种将驾驶员对方向盘的操作信号转换为电信号,再传递给转向机,从而控制车轮完成相应的转向动作的技术。经纬恒润推出的线控转向控制系统SbW,分为路感模拟器与转向执行器,皆采用全冗余设计及主从控制方案,同时,按照ISO26262与DIN70065进行功能安全与降级…

uniapp使用scroll-view嵌套时不触发滚动事件

参考链接:微信文档:https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html uniapp文档: https://uniapp.dcloud.net.cn/component/scroll-view.html布局代码:<scroll-view scroll-y class="scroll-box" bindscrolltolower="scro…

OpenCL 调用关系

学习 OpenCL,概念很多,理解不深,所以看示例代码时比较糊涂。 于是,把调用关系简单画了个图:希望能加深理解吧。

SAP SMW0 配置EXCEL 上载模板,供其他tcode 下载模板

本文演示如何在自定义的tcoe 中,可以点击下载保存好的默认excel模板: 1. 打开 SMWO: 筛选 直接点新增 点浏览,找你本机的 excel 模板,进行上载 上载完后, 回到上载程序,点击,就能弹出需要下载的excel模板了

OP51常见问题(自动安装座板)

座板放置歪斜 1.夹爪夹住座板后,上升-->翻转180-->横移-->下降放置。需要准确放入铆钉内。 2.因为座板和夹爪都是金属件,所以旋转和横移过程中可能会发生水平方向的偏移,导致放置时对孔失败。 如果放置失败座板浮起,对光检测到了,上方的大压块会下压一次,尝试将…

YASKAWA点焊机器人维修的流程

在现代工业生产中,工业机器人发挥着至关重要的作用,而YASKAWA点焊机器人更是其中的佼佼者。然而,就像任何设备一样,机器人也会遭遇故障,这时候安川机器人维修、YASKAWA机器人维修以及工业机器人维修就显得尤为关键。一、机器人故障的常见类型YASKAWA点焊机器人在长时间的工…

Camstar中ToggleContainer标题样式改成建模框一样的

😘宝子:除非不再醒来,除非太阳不再升起,不然都请你好好生活,挣扎着前进,开心的笑。(●◡●)