AT_arc195_d [ARC195D] Swap and Erase 题解

news/2025/11/20 7:30:49/文章来源:https://www.cnblogs.com/Rainsheep/p/19244713

我们可以把操作过程分成两个阶段,毕竟先进行全部的交换操作,再进行所有的删除操作,对比一边换一遍删是不会更劣的。

接下来还需要注意到一个结论,一个数至多被交换一次。我们考虑一次交换带来的影响,设相邻的两个数 \(x,y\) 交换后最多可以减少两次操作,即 \(x, y, x, y\) 我们交换中间两个数的情况,那么我们有 \(1\) 的正收益。考虑交换两次是什么样子,我们把 \(x, y, z\) 变成了 \(y, z, x\),最好情况下的排列是 \(y, x, y, z, x\),我们操作了两次但也只减少了两次操作,所以也是不优的,大于两次的也很容易这么贪心的证出来。

基于这个事实,考虑有 \(dp_{i,0/1}\) 表示清空前 \(i\) 位,且第 \(a_i, a_{i-1}\) 位不进行/进行交换的最小操作次数。转移讨论:

设命题 \(P = a_i \ne a_{i - 1}, Q = a_i \neq a_{i - 2}, R = a_i \ne a_{i - 3}\)

  • 当不交换时,讨论前一位的交换情况。

\[dp_{i, 0} = \min(dp_{i - 1, 0} + P, dp_{i - 1, 1} + Q) \]

  • 当交换时,基于上面的分析第 \(i - 1\) 位不能再做交换,那么考虑讨论 \(i - 2\) 的交换。

\[dp_{i, 1} = 1 + P + \min(dp_{i - 2, 0} + Q, dp_{i - 2, 1} + R) \]

直接转移即可做到 \(O(n)\)。代码。

Ex

维护一个序列,每次可以区间加、区间赋值,询问把任意一个区间变成空数列的最小操作次数。\(n, m \le 10^5\)

考虑上面的 dp 实质上在做 \(\min +\) 卷积,考虑 ddp,我们把转移放到矩阵上。

\[\begin{bmatrix}P& Q& +\infty& +\infty\\+\infty& +\infty& P+Q+1& P+R+1\\0& +\infty& +\infty& +\infty\\+\infty& 0& +\infty& +\infty \end{bmatrix} \begin{bmatrix}dp_{i-1,0}\\dp_{i-1,1}\\dp_{i-2,0}\\dp_{i-2,1} \end{bmatrix} = \begin{bmatrix}dp_{i,0}\\dp_{i,1}\\dp_{i-1,0}\\dp_{i-1,1} \end{bmatrix} \]

那考虑操作分别的意义:

  • 区间加

注意到区间内部的数并不会因为区间加而改变大小关系,只有 \([l, l + 2], [r + 1, r + 3]\) 的会变动,只需要暴力维护这些位置即可,注意到上述的命题 \(P, Q, R\) 都会随着 \(a\) 改变,所以还需要维护一棵支持区间加、区间推平、单点查的线段树。

  • 区间推平

边界依然按照刚才的方法暴力,注意到推平后 \(P = Q = R = 0\),那么中间的矩阵形状是固定的,只需要预处理这样的矩阵的 \(k\) 次方直接 pushdown 即可。

  • 询问

先算出 \(dp_{1,0/1}, dp_{2,0/1}\) 的值,然后乘上区间的矩阵即可。代码。

// ubsan: undefined
// accoders
// 如果命运对你缄默, 那就活给他看。
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast", "inline", "-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
typedef long long LL; 
// #define int LL
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int n, m, a[maxn]; 
inline int cmi(int& x, int y) {if(y < x) x = y; return x;
}
struct mat {int g[4][4];inline void E () { for(int i = 0; i < 4; ++ i)for(int j = 0; j < 4; ++ j) g[i][j] = INF * (i != j); }  mat () { memset(g, 0x3f, sizeof g); }inline mat operator * (const mat& b) const {mat c;for(int i = 0; i < 4; ++ i)for(int k = 0; k < 4; ++ k)if(g[i][k] != INF) for(int j = 0; j < 4; ++ j) c.g[i][j] = min(c.g[i][j], g[i][k] + b.g[k][j]);return c; }inline bool operator == (const mat& b) const {for(int i = 0; i < 4; ++ i)for(int j = 0; j < 4; ++ j) if(g[i][j] != b.g[i][j]) return 0;return 1;}inline void print() {for(int i = 0; i < 4; ++ i, cout << '\n')for(int j = 0; j < 4; ++ j) {if(g[i][j] == INF) cout << -1 << ' ';else cout << g[i][j] << ' '; }}
} ID; 
inline bool operator != (const mat& a, const mat& b) { return !(a ==  b); }
inline mat make(int P, int Q, int R) {mat a;a.g[0][0] = P, a.g[0][1] = Q;a.g[1][2] = P + Q + 1, a.g[1][3] = P + R + 1;a.g[2][0] = a.g[3][1] = 0; return a;
}
mat pw[maxn]; 
inline void init() {pw[0].E(), ID.E(); mat e = make(0, 0, 0); for(int i = 1; i <= n; ++ i) pw[i] = pw[i - 1] * e; 
}
namespace sgt1 {int as[maxn << 2], ad[maxn << 2];inline void ev(int u, int ass, int add) {if(ass) as[u] = ass, ad[u] = 0; ad[u] += add;}inline void dw(int u) {ev(u << 1, as[u], ad[u]);ev(u << 1 | 1, as[u], ad[u]); as[u] = 0, ad[u] = 0; }inline void modf(int u, int l, int r, int ql, int qr, int ass, int add) {if(ql <= l && r <= qr) return ev(u, ass, add);int mid = l + r >> 1; dw(u); if(ql <= mid) modf(u << 1, l, mid, ql, qr, ass, add);if(qr > mid) modf(u << 1 | 1, mid + 1, r, ql, qr, ass, add); }inline int Q(int u, int l, int r, int p) {if(l == r) return as[u] + ad[u];int mid = l + r >> 1; dw(u); if(p <= mid) return Q(u << 1, l, mid, p);else return Q(u << 1 | 1, mid + 1, r, p);}
}
inline mat fpow(mat a, int b) {mat c; c.E();for(; b; b >>= 1, a = a * a)  if(b & 1) c = c * a;return c;
}
namespace sgt2 {mat g[maxn << 2];mat as[maxn << 2];inline void pu(int u) {g[u] = g[u << 1 | 1] * g[u << 1 ]; }inline void dw(int u, int l, int r) {int mid = l + r >> 1;if(as[u] != ID) {as[u << 1] = g[u << 1] = pw[mid - l + 1];as[u << 1 | 1] = g[u << 1 | 1] = pw[r - mid]; as[u].E(); }}inline void modf1(int u, int l, int r, int p, mat k) {if(l == r) return g[u] = k, void();int mid = l + r >> 1; dw(u, l, r);if(p <= mid) modf1(u << 1, l, mid, p, k);else modf1(u << 1 | 1, mid + 1, r, p, k); pu(u); }inline void modf2(int u, int l, int r, int ql, int qr) {// if(as[u] != ID) return ;if(ql <= l && r <= qr) return as[u] = g[u] = pw[r - l + 1], void();dw(u, l, r); int mid = l + r >> 1;if(ql <= mid) modf2(u << 1, l, mid, ql, qr);if(qr > mid) modf2(u << 1 | 1, mid + 1, r, ql, qr);pu(u); }inline mat Q(int u, int l, int r, int ql, int qr) {if(ql <= l && r <= qr) return g[u];int mid = l + r >> 1; dw(u, l, r); if(qr <= mid) return Q(u << 1, l, mid, ql, qr);if(ql > mid) return Q(u << 1 | 1, mid + 1, r, ql, qr);return Q(u << 1 | 1, mid + 1, r, ql, qr) * Q(u << 1, l, mid, ql, qr);}inline void build(int u, int l, int r) {as[u].E(), g[u].E();if(l == r) return ;int mid = l + r >> 1;build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r), pu(u); }
}
inline void maintain(int l, int r) {for(int i = l - 3; i <= min(n, l + 2); ++ i) {if(i >= 1) a[i] = sgt1::Q(1, 1, n ,i);if((i - 3 >= 0) && i >= l) {int P = a[i] != a[i - 1];int Q = a[i] != a[i - 2];int R = a[i] != a[i - 3]; sgt2::modf1(1, 1, n, i, make(P, Q, R)); }}for(int i = r - 2; i <= min(r + 3, n); ++ i) {if(i >= 1) a[i] = sgt1::Q(1, 1, n, i); if((i - 3 >= 0) && (i > r)) {int P = a[i] != a[i - 1];int Q = a[i] != a[i - 2];int R = a[i] != a[i - 3]; sgt2::modf1(1, 1, n, i, make(P, Q, R)); }}
}
inline void solve0(int l, int r, int x) {sgt1::modf(1, 1, n, l, r, 0, x);maintain(l, r); 
}
inline void solve1(int l, int r, int x) {sgt1::modf(1, 1, n, l, r, x, 0);maintain(l, r); if(l + 3 <= r) sgt2::modf2(1, 1, n, l + 3, r); 
}
inline int Q(int l, int r) {if(l == r) return 1;auto debug = ID;a[l] = sgt1::Q(1, 1, n, l), a[l + 1] = sgt1::Q(1, 1, n, l + 1);mat ans;// al, al+1ans.g[0][0] = 1 + (a[l] != a[l + 1]);ans.g[1][0] = ans.g[0][0] + 1;ans.g[2][0] = 1;ans.g[3][0] = INF;if(l + 2 <= r) {auto G = sgt2::Q(1, 1, n, l + 2, r);ans = G * ans;}return min(ans.g[0][0], ans.g[1][0]); 
}
signed main() {freopen("swap.in", "r", stdin);freopen("swap.out", "w", stdout);ios :: sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> m;init();sgt2::build(1, 1, n); for(int i = 1; i <= n; ++ i) {cin >> a[i];sgt1::modf(1, 1, n, i, i, a[i], 0);if(i >= 3) sgt2::modf1(1, 1, n, i, make(a[i] != a[i - 1], a[i] != a[i - 2], a[i] != a[i - 3])); }for(int i = 1; i <= m; ++ i) {int op, l, r, x;cin >> op >> l >> r;if(op == 1) {cin >> x;solve0(l, r, x); } else if (op == 2) {cin >> x, solve1(l, r, x);  } else {cout << Q(l, r) << '\n'; }}return 0;
}

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

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

相关文章

AI元人文理论体系:从价值原语化到阈值管理的完整建构

AI元人文理论体系:从价值原语化到阈值管理的完整建构 摘要 AI元人文理论体系提出了一种解决智能时代价值困境的创新框架。该体系以"三值纠缠模型"为哲学基础,通过"价值原语化"方法论将抽象价值降…

Office 已知问题 GROOVEEX.DLL 带崩进程

这是一位老师向我反馈的问题,我的一个 WPF 应用程序在他的设备上,任何弹出保存文件对话框或打开文件对话框的功能,都会导致进程闪退。经过进一步调查,我发现他电脑上任何软件弹出文件保存对话框都会闪烁,问题本身…

AI元人文:价值原语化理论中的阈值管理机制

AI元人文:价值原语化理论中的阈值管理机制 摘要:本文旨在系统阐述AI元人文理论中价值原语化与阈值管理的有机统一关系。价值原语化通过构建“价值原语”这一不可再分的基本行为单元,为解决智能体的价值困境提供了本…

读社会工程卷2:解读肢体语言01非语言交流

读社会工程卷2:解读肢体语言01非语言交流1. 非语言交流 1.1. 保罗艾克曼博士1.1.1. 《情绪的解析》1.1.2. 《心理学家的读脸术:解读微表情之下的人际交往情绪密码》​1.2. 身体的每个部位都能表达我们的情绪1.2.1. 这…

知识学报:入门(1)

未完成不是题解不是教学!!! 11.20 CSES 1068 模拟。 CSES 1083 模拟。 CSES 1069 模拟。 CSES 1094 每次操作对某个数加一,要求从左到右不减小,求最小操作次数。 从左到右每个检查,如不满足就加到和前一个相同。…

英国网络安全法案强化关键基础设施监管新规

英国政府推出《网络安全与韧性法案》,对医疗、能源、交通和数字服务等关键基础设施实施更严格的安全标准,包括基于营业额的罚款制度和24小时事件报告要求,首次将托管服务提供商和数据中心纳入监管范围。更严格的网络…

开发一个出厂就是最高权限的手机或者用linux手机虚拟化运行安卓系统

开发一个出厂就是最高权限的手机或者用linux手机虚拟化运行安卓系统开发一个出厂就是最高权限的手机或者用linux手机虚拟化运行安卓系统

0#120;c000000f进不了系统怎么修复

1.BCD丢失或BCD引导文件受损 2.系统文件丢失或损坏 3.数据线或电源线接触不良/损坏 4.设备出现了问题 二、解决方法1.检查外部设备,有时电脑出现了蓝屏0xc000000f进不了系统的情况计算机的外部设备可能存在问题。 2.使…

.csv linux

您提到的 .csv 文件,通常是指以逗号分隔的值(Comma-Separated Values)文件,常用于存储表格数据。在 Linux 系统中,处理 .csv 文件的常用命令和脚本如下:一、查看 .csv 文件内容1. 使用 cat 命令查看文件内容cat …

1000多的vivo手机哪款比较好

Vivo Y77售价1499起,首先该手机采用了旗舰级80W双芯闪充,还搭载了天玑930八核处理器等。处理器:天玑930八核处理器屏幕尺寸:6.64英寸电池容量:4500mHA运行内存:8GB屏幕刷新率:120Hz是否5G:是摄像头:置5000万像…

.so文件 linux

.so 文件是 Linux 系统中用于动态链接库(Dynamic linking Library)的扩展名,通常指的是 共享对象文件(Shared Object File),也就是 shared library。一、.so 文件的作用.so 文件是 Linux 系统中动态链接库的实现…

AI元人文思想体系综论:构建数字文明的伦理基石

AI元人文思想体系综论:构建数字文明的伦理基石 “AI元人文”是一个层层递进、逻辑自洽、且具备强大实践指向的理论体系。它从一种深刻的哲学观照出发,最终旨在为人工智能时代的社会治理与文明建构提供一套完整的“操…

AI元人文:从三值纠缠到阈值管理的理论建构与实践路径

AI元人文:从三值纠缠到阈值管理的理论建构与实践路径 摘要:本文系统性地阐述了“AI元人文”理论体系,这是一个旨在应对数字文明时代复杂挑战的原创性思想框架。体系以“三值纠缠理论”为哲学基石,揭示了欲望值、客…

【第7章 I/O编程与异常】文件操作补全程序题

题目1:基础文本读取(r模式) 补全程序,读取文本文件的前2行并打印(去除每行首尾空格): # 文件content.txt内容: # 第一行:Python文件操作 # 第二行:基础模式练习 # 第三行:进阶技巧 with open("…

【I/O编程与异常】文件操作补全程序题

题目1:基础文本读取(r模式) 补全程序,读取文本文件的前2行并打印(去除每行首尾空格): # 文件content.txt内容: # 第一行:Python文件操作 # 第二行:基础模式练习 # 第三行:进阶技巧 with open("…

应用安全 --- IDAPro函数控制流分析

应用安全 --- IDAPro函数控制流分析函数控制流也叫交叉引用流,用于查看某个函数调用的所有其他函数 右键函数名称选择 来自交叉引用,查看引用图 我们可以通过分析发现调用的越深越有可能是重要函数 调用其他函数越多…

应用安全 --- IDAPro 函数控制流分析

应用安全 --- IDAPro 函数控制流分析函数控制流也叫交叉引用流,用于查看某个函数调用的所有其他函数 右键函数名称选择 来自交叉引用 我们可以通过分析发现调用的越深越有可能是重要函数 调用其他函数越多越有可能是初…

应用安全 --- IDA Pro 函数控制流

应用安全 --- IDA Pro 函数控制流函数控制流也叫交叉引用流,用于查看某个函数调用的所有其他函数 右键函数名称选择 来自交叉引用 我们可以通过分析发现调用的越深越有可能是重要函数 调用其他函数越多越有可能是初始…

AI元人文:阈值理论体系——自由、公平、安全的动态边界与调控艺术

AI元人文:阈值理论体系——自由、公*、安全的动态边界与调控艺术 摘要:本文在“AI元人文三值纠缠理论”的基础上,提出并系统论述了“阈值理论体系”。该体系认为,健全的个人、组织与文明并非追求自由、公*、安全三…

应用安全 --- 看门狗函数

应用安全 --- 看门狗函数看门狗函数就是第一个执行的安全检查函数,不会对环境有任何影响,目的就是检查代码的执行环境是不是安全