1.22 CW 模拟赛 T2. Mashmokh and Reverse Operation

news/2025/1/24 13:33:33/文章来源:https://www.cnblogs.com/YzaCsp/p/18689410

思路

容易想到把区间建成满二叉树, 太 \(\rm{trick}\)

考虑把翻转操作搞到树上去

最初的想法是显然的, 对于 \(q_i\) 的询问, 显然要把从 \(2 \sim q_i + 1\) 层的左右儿子全部翻转, \(1\) 层是叶子节点

具体的, 可以把对于 \(u\) 的大区间这样处理

  • 翻转 \(ls\)
  • 翻转 \(rs\)
  • \(ls, rs\) 交换

前两个显然是递归下去的, 我们只需要对于每个节点, 维护第三个操作对答案的影响

块内处理

块内相当于原来的贡献是 \(\sum [a_i>a_j,i\in left,j\in right]\)
之后变成了 \(\sum [a_i>a_j,i\in right,j\in left]\)

考虑这个东西可以在归并排序的时候 \(\mathcal{O} (L \log L)\) 计算, 其中 \(L = 2^n\)


颓了一上午继续学, 以后手机放音乐就可以忍住不玩手机
这几天就是正常学就行了, 不要太颓
手机肯定是放外面的, 然后就是该怎么学怎么学, 可以考虑挂个什么音乐之类的就不颓了


具体的, 我们考虑归并排序的实质, 就是对于一个序列先分成这样的一颗满二叉树, 然后合并
在这个过程中, 我们显然是可以顺带求出逆序对个数的

当然如果你没有意识到, 在满二叉树上进行一个权值线段树的合并也是可以的
具体的, 你注意到线段树合并的复杂度大概是小的那一棵树的复杂度, 容易发现最劣 \((\)即每次两棵树大小相当\()\) 都是 \(\log\) 级别的

这个好像是一个 \(\rm{trick}\)


解决完这个问题, 如何处理每次答案呢
显然暴力枚举或者仅和上面一样模拟都是纯神经, 所以考虑一个传统 \(\rm{trick}\) , 即每次操作对答案的影响

首先我们知道这些信息

  • 二叉树中每个节点对应的区间的顺逆序对个数
  • 每次操作需要对那些层进行翻转

考虑这个问题的子问题, 即每一层进行翻转产生的贡献
不难发现, 我们可以直接计算出每一层的顺逆序对交换之后的贡献, 块内部分轻松解决

块间处理

你使用脑子, 发现交换前后块间逆序对个数不受影响, 那直接不管这个就行了

最终处理

首先归并处理每个节点的顺逆序对个数

然后每次询问查询 \(2 \sim q_i\) 层的节点的顺逆序对之差 \((\)注意这个顺逆序对的定义是会变的\()\)
如果你提前统计每一层的顺逆序对之差, 那么诗人能做

实现

框架

首先归并两次求层内逆序对个数, 标记一下

然后处理的时候一次处理一层即可

代码

#include <bits/stdc++.h>
#define int long long
typedef unsigned long long ull;const int MAXN = 2e6 + 20;
const int MAXLOGN = 25;namespace Fast_IO {char buf[1 << 20], *p1, *p2;#define getchar() (p1 == p2 and (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? 0 : *p1++)void read() {}template <class T, class ...T1>void read(T &x, T1 &...y) {x = 0;char ch = getchar(); bool f = 1;for (; ch < '0' or ch > '9'; ch = getchar()) if (ch == '-') f = 0;for (; ch >= '0' and ch <= '9'; x = x * 10 + (ch & 15), ch = getchar());x = (f ? x : -x);read(y...);}void print(int x) {if (x < 0) putchar('-'), x = -x;if (x > 9) print(x / 10);putchar(x % 10 + '0');}void print(int x, char c) { print(x), putchar(c); }
} using namespace Fast_IO;int n, m;
int inver[2][MAXLOGN];
int val[MAXN], bin[MAXN], q[MAXN];ull k1, k2, threshold;
ull xorShift128Plus() {ull k3 = k1, k4 = k2;k1 = k4;k3 ^= (k3 << 23);k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);return k2 + k4;
}
void gen(int n, int m, int threshold, ull _k1, ull _k2) {k1 = _k1, k2 =_k2;for (int i = 1; i <= (1 << n); i++) bin[i] = val[i] = xorShift128Plus() % threshold + 1;for (int i = 1; i <= m; i++) q[i] = xorShift128Plus() % (n + 1);
}/*归并排序计算每个节点的逆序对个数*/
class mergesort
{
private:public:/*合并*/int merge(const int *a, size_t asize, const int *b, size_t bsize, int *c) {size_t i = 1, j = 1, k = 1;int res = 0; // 逆序对个数while (i <= asize && j <= bsize) if (b[j] < a[i]) res += asize - i + 1, c[k++] = b[j++]; else c[k++] = a[i++];for (; i <= asize; i++) c[k++] = a[i];for (; j <= bsize; j++) c[k++] = b[j];return res;}int tmp[MAXN];/*倍增法处理逆序对数量*/void solve(int *val, size_t n, int type) {memset(tmp, 0, sizeof tmp);for (size_t seg = 1, res = 2; seg < n; seg <<= 1, res++) for (size_t left1 = 0; left1 < n - seg; left1 += seg + seg) {size_t right1 = left1 + seg, left2 = right1, right2 = std::min(left2 + seg, n);inver[type][res] += merge(val + left1, right1 - left1, val + left2, right2 - left2, tmp + left1);for (size_t i = left1 + 1; i <= right2; i++) val[i] = tmp[i];}}
} ms;signed main()
{read(n, m, threshold, k1, k2);gen(n, m, threshold, k1, k2);int logn = n;n = (1 << n);ms.solve(bin, n, 0);int sum = inver[0][logn];std::reverse(val + 1, val + n + 1); for (int i = 1; i <= n; i++) bin[i] = val[i];ms.solve(bin, n, 1);int tot = 0;for (int i = 1; i <= m; i++) {for (int j = 2; j <= q[i] + 1; j++) std::swap(inver[0][j], inver[1][j]);int ans = 0; for (int j = 1; j <= logn; j++) ans += inver[0][j + 1];tot ^= (ans * i);}print(tot);return 0;
}

总结

常用的树上 \(\rm{trick}\)

然后就是善于把这类问题转化成对答案的 \(\Delta\) 的处理, 会方便很多

对归并的理解是一坨, 赛时根本想不到

常用的优化办法: 把一定一起操作的绑定到一起

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

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

相关文章

中电金信首次通过数据管理能力成熟度(DCMM)四级认证

日前,中国电子信息行业联合会发布《关于公布获得数据管理能力成熟度等级证书单位的通知(第十四批)》,中电金信正式通过数据管理能力成熟度(DCMM)等级认定——量化管理级(4级)。DCMM即数据管理能力成熟度评估模型(Data management Capability Maturity Model),是我国首…

执子之手与子偕老:镌刻在时光深处的爱情传奇

执子之手与子偕老:镌刻在时光深处的爱情传奇“死生契阔,与子成说。执子之手,与子偕老。” 这出自《诗经・邶风・击鼓》的千古名句,如同一首跨越千年的悠扬情歌,萦绕在人类情感的天际,描绘出爱情最纯粹、最美好的模样,承载着人们对永恒相伴、不离不弃的深深期许。它不仅仅…

二维数点问题

二维数点问题。P10814 【模板】离线二维数点 询问区间 \([l,r]\) 内,在值域为 \([0,x]\) 中数的个数。 想象这是个二维平面,我们要求的就是矩形内点的个数。通常用 cdq 做,将询问拆成两个点,将点按照x坐标排序,按照y坐标加入到树状数组中(为了满足第二条限制),这时就依次…

CS162 23Fall总结

CS 162 23Fall Lab 总结 PintOS是一个x86架构的教育用操作系统,它支持多线程,加载并运行用户程序,以及文件系统。骨架代码只提供了很简单的实现,本Lab需要丰富并增强这些模块的功能。本实验提供Bochs2和QEMU3模拟器模拟x86 CPU和相应外设来运行并调试PintOS.PintOS源码结构…

《汇编语言》阅读笔记

如题汇编语言 首先,我必须赞扬王爽老师,这是我见过写的最好的教科书了. 然后要注意,汇编语言这本书的前提是8086PC机十六位处理器.还要学x86和x64以及其他奇奇怪怪的架构的汇编 全称 AH&AL=AX(accumulator):累加寄存器 BH&BL=BX(base):基址寄存器 CH&CL=CX(co…

【unity】学习制作2D横板冒险游戏-3-

添加野猪添加刚体2D组件,碰撞组件,该碰撞组件是确保野猪能跟地面碰撞添加玩家图层和敌人图层,并应用,使野猪和玩家不会彼此被推着走碰撞剔除中选择Player和Enemy再增加一个碰撞组件当作触发器,设置如下,该碰撞组件是确保人物和怪物的互动基本属性及其计算 再如图路径下创建…

远控流畅游戏,我用过最棒工具ToDesk

孤独乏味人又懒,能够干嘛来消遣?手游、端游都好玩,没有高端设备在身边,也是能够轻松玩!究竟怎么实现的?其实就是通过ToDesk这种专业的远程控制软件来随时随地操作异地的目标设备从而帮助实现更丝滑给力的远程游戏畅玩体验!当然,用户能够借助完成这需求的辅助工具并不止…

C# Odbc Informix读取中文方法

一。 部署好informix服务器后 二。 在windows主机安装好Informix Client-SDK, 这个软件客户端时免费的,可以在官网下载 三。配置好ODBC连接 1.用户名密码服务端口自行填写 2.关于客户语言的配置要使用以下参数: Client Locale -> en_US.CP1252 Database Locale -> en_…

ToDesk远程连接几项模式区别何在?

对于很多用过ToDesk远程控制软件进行随时随地跨系统、跨设备操作的小伙伴们来说,它无疑能解决做种场景下问题,无论是在职场工作中,还是日常生活中,均能带来很多便捷!虽然轻松使用很简单,但很多所不知道的是其实应对不同的情况,选择不同的连接模式更有益!以下木木小编就…

如何在网站后台修改首页?

修改网站后台首页通常涉及对后台管理界面的调整。以下是详细步骤:登录后台:使用管理员账号登录网站后台管理系统。 进入模板管理:在后台管理系统中找到“模板管理”或“模板文件管理”选项。 编辑模板文件:找到后台首页的模板文件(如index.htm或index.php),使用代码编辑…

一些关于软件测试中登录模块的测试用例

以下是一份针对软件测试中登录模块较为完整的测试用例,涵盖了各种常见情况,尽量保证较高的覆盖率:一、功能测试1. 正常登录 2. 用户名错误 3. 密码错误 4. 用户名和密码都错误 5. 用户名和密码为空 6. 仅用户名为空 7. 仅密码为空 8. 用户名和密码长度极限值 9. 记住用户名…

如何修改网站管理员admin的信息?

登录网站后台:使用管理员账号(通常是admin)登录到网站的后台管理界面。进入用户管理页面:在后台管理界面中,找到“用户”、“用户管理”或类似的菜单选项,点击进入用户管理页面。找到管理员账号:在用户管理页面中,找到管理员账号(通常是admin),点击账号名称或编辑按…