NOIP集训 P11071 「QMSOI R1」 Distorted Fate 题解

对本题的评价:有思维含量的线段树好题。曲子好听,曲绘好看,曲师人品好,谱子写得好,鸠好看
题解: P11071 「QMSOI R1」 Distorted Fate
给定一个长度为 \(n\) 的数组 \(A\),你需要完成以下 \(q\) 次操作。
1.1 l r x将 \(A_i(l\le i\le r)\) 异或上 \(x\)。
2.2 l r求:
\]
其中 \(\bigcup\) 表示按位或。
Input
第一行输入两个数 \(n\) 和 \(q\),代表数组长度和操作的次数。
第二行输入 \(n\) 个整数,第 \(i\) 个数代表 \(A_i\) 的值。
接下来 \(q\) 行,每行输入三个整数 \(opt,l,r\) 。
若 \(opt=1\) ,则再输入一个整数 \(x\) 表示将区间 \([l,r]\) 中 \(A_i\) 异或上 \(x\)。
若 \(opt=2\) ,则代表这是一次查询。
Output
对于每个查询,输出一行一个整数代表所求式子的值 \(\bmod \ 2^{30}\) 的结果。
Note
对于所有数据,满足 \(0\le a_i,x<2^{30},1\le l\le r\le n\) 。
空间限制 \(100MB\) 。
分析
很自然往拆位的思路去想。
因为空间限制卡的很死,所以不能直接在线做。
先把操作离线下来,每一位单独做。由于是前缀按位或,相当于对于 \([l,r]\) 的 \(0/1\) 序列,找到第一个出现的 \(1\) 的位置,其后包括它本身都会对答案有贡献。
这样就可以考虑线段树上每个节点维护两个值 \(pos_0\) 和 \(pos_1\) ,分别表示值域内第一次出现 \(0\) 和 \(1\) 的位置,建树时如果 \(A_i\) 当前处理的位置上为 \(1\) 就把 \(pos_1\) 赋成 \(i\), \(pos_0\) 赋成极大值;当前位置上为 \(0\) 就反过来。每次处理如果 \(x_i\) 这一位为 \(1\) 就可以直接把 \([l,r]\) 的 \(pos_0, pos_1\) 交换(等价于异或),用 \(tag_u\) 延迟下放标记即可。
每次在同一片内存空间上建树,每一位操作可以重复在这一棵线段树上进行。记得清空标记。
AC代码:
#include<bits/stdc++.h>
using namespace std;
inline int read() {
int f = 1, otto = 0;
char a = getchar();
while(!isdigit(a)) {
if(a == '-') f = -1;
a = getchar();
}
while(isdigit(a)) {
otto = (otto << 1) + (otto << 3) + (a ^ 48);
a = getchar();
}
return f * otto;
}
const int maxn = 2e5 + 10, mo = 1 << 30, inf = 1 << 30;
int bit, a[maxn], ans[maxn], pos0[maxn << 2], pos1[maxn << 2];
struct REQ{
int op, l, r, x;
}req[maxn];
bool tag[maxn << 2];
void upd(int u) {
pos0[u] = min(pos0[u << 1], pos0[u << 1 | 1]), pos1[u] = min(pos1[u << 1], pos1[u << 1 | 1]);
return;
}
void build(int u, int l, int r) {
if(l == r) {
if((a[l] >> bit) & 1) pos0[u] = inf, pos1[u] = l;
else pos0[u] = l, pos1[u] = inf;
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
return upd(u), void(0);
}
void pushdown(int u) {
if(!tag[u]) return;
swap(pos0[u << 1], pos1[u << 1]), swap(pos0[u << 1 | 1], pos1[u << 1 | 1]);
tag[u << 1] ^= 1, tag[u << 1 | 1] ^= 1;
tag[u] = 0; //记得清空tag
return;
}
void Do(int u, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) {
tag[u] ^= 1;
swap(pos0[u], pos1[u]);
return;
}
pushdown(u);
int mid = l + r >> 1;
if(ql <= mid) Do(u << 1, l, mid, ql, qr);
if(mid < qr) Do(u << 1 | 1, mid + 1, r, ql, qr);
return upd(u), void(0);
}
int ask(int u, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) return pos1[u];
pushdown(u);
int mid = l + r >> 1, ret = inf;
if(ql <= mid) ret = min(ret, ask(u << 1, l, mid, ql, qr));
if(mid < qr) ret = min(ret, ask(u << 1 | 1, mid + 1, r, ql, qr));
return ret;
}
int main() {
int n = read(), q = read();
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= q; i++) {
req[i].op = read(), req[i].l = read(), req[i].r = read();
if(req[i].op == 1) req[i].x = read();
}
for(bit = 0; bit <= 30; bit++) {
memset(tag, 0, sizeof tag);
build(1, 1, n);
for(int i = 1; i <= q; i++) {
if(req[i].op == 1 && (req[i].x >> bit) & 1) Do(1, 1, n, req[i].l, req[i].r);
if(req[i].op == 2) {
int res = ask(1, 1, n, req[i].l, req[i].r);
if(res != inf) ans[i] = (ans[i] + 1ll * (req[i].r - res + 1) * (1 << bit) % mo) % mo;
}
}
}
for(int i = 1; i <= q; i++) {
if(req[i].op == 2) printf("%d\n", ans[i]);
}
return 0;
}
NOIP集训 P11071 「QMSOI R1」 Distorted Fate 题解的更多相关文章
- LuoguP7127 「RdOI R1」一次函数(function) 题解
Content 设 \(S_k\) 为直线 \(f(x)=kx+k-1\),直线 \(f(x)=(k+1)x+k\) 与 \(x\) 轴围成的三角形的面积.现在给出 \(t\) 组询问,每组询问给定一 ...
- 「POI2011 R1」Conspiracy
「POI2011 R1」Conspiracy 解题思路 : 问题转化为,将点集分成两部分,其中一部分恰好组成一个团,其中另一部分恰好组成一个独立集. 观察发现,如果求出了一个解,那么答案最多可以在这个 ...
- LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)
题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...
- LOJ #2540. 「PKUWC 2018」随机算法(概率dp)
题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...
- Note -「动态 DP」学习笔记
目录 「CF 750E」New Year and Old Subsequence 「洛谷 P4719」「模板」"动态 DP" & 动态树分治 「洛谷 P6021」洪水 「S ...
- 「AHOI / HNOI2017」影魔
「AHOI / HNOI2017」影魔 题目描述 解决这类比较复杂的区间贡献问题关键在于找到计算的对象. 比如这道题,我们计算的对象就是区间中间的最大值. 对于点\(i\),我们找到左边第一个比他大的 ...
- 「GXOI / GZOI2019」简要题解
「GXOI / GZOI2019」简要题解 LOJ#3083. 「GXOI / GZOI2019」与或和 https://loj.ac/problem/3083 题意:求一个矩阵的所有子矩阵的与和 和 ...
- [LOJ 2022]「AHOI / HNOI2017」队长快跑
[LOJ 2022]「AHOI / HNOI2017」队长快跑 链接 链接 题解 不难看出,除了影响到起点和终点的射线以外,射线的角度没有意义,因为如果一定要从该射线的射出一侧过去,必然会撞到射线 因 ...
- 「国家集训队」小Z的袜子
「国家集训队」小Z的袜子 传送门 莫队板子题. 注意计算答案的时候,由于分子分母都要除以2,所以可以直接约掉,这样在开桶算的时候也方便一些. 参考代码: #include <algorithm& ...
- P7708「Wdsr-2.7」八云蓝自动机 Ⅰ
*X. P7708「Wdsr-2.7」八云蓝自动机 Ⅰ. 摘自 分治与根号数据结构学习笔记 第三部分 莫队 例题 X.. 一道莫队好题.私以为本题最有价值的地方在于对单点修改的转化以及对交换两个数的处 ...
随机推荐
- 解锁DeepSeek深度应用,天翼云GPU云主机强势破局!
在人工智能重塑世界的当下,一场影响深远的科技变革正在悄然上演,DeepSeek系列模型在诸多领域掀起热潮.企业级AI模型的训练与部署,不仅是技术的角力场,更是决定企业兴衰的生死线.每一次算法的迭代革新 ...
- 你还不会使用curl发送请求吗?一篇博客搞定!
前言:以下均为Windows使用,使用前不需要任何准备,打开命令提示符根据指令即可使用关键字: curl 注意: 建议在请求前ping一下 ping http://www.123.com 或 ping ...
- STC内部扩展RAM的应用
RAM是用来在程序运行中存放随机变量的数据空间,51单片机默认的内部RAM只有128字节,52单片机增加至256字节,STC89C52增加到512字节,STC89C54.55.58.516等增加到12 ...
- autMan奥特曼机器人-出现argument list too long报错的解决方法
当你运行一段时间autMan后,可能会出现argument list too long的报错,那是你主机系统限制了autMan运行插件的参数长度,导致的报错,如下: 查看当前ARG_MAX的值 在 L ...
- 机器学习 | 强化学习(2) | 动态规划求解(Planning by Dynamic Programming)
动态规划求解(Planning by Dynamic Programming) 动态规划概论 动态(Dynamic):序列性又或是时序性的问题部分 规划(Programming):最优化一个程序(Pr ...
- C# fleck websocket使用
转载于:https://www.itspeeding.com/article/28 1.web页面 1 <html lang="en" xmlns="http:// ...
- 基于webman实现的服务层框架-webman-biz-framework
简介 webman的基础上扩展的一个服务层框架,基于分层体系结构的代码模式. 如果觉得有用,可以帮我在webman-biz-framework点个小星星哟,也希望大家交流 分层体系结构的代码模式 什么 ...
- go mod 安装bee 报错
报错信息 go: github.com/beego/bee imports github.com/beego/bee/cmd imports github.com/beego/bee/cmd/comm ...
- laradock 安装扩展程序 pcntl
起因 运行workman脚步的时候,PHP 提示缺少 pcntl 扩展 Config git:(master) php start.php -d Please install pcntl extens ...
- 算法分析-回溯算法-求解N皇后问题
一.题目需求 n皇后问题是一道比较经典的算法题.它研究的是将n个皇后放置在一个n×n的棋盘上,使皇后彼此之间不相互攻击. 即任意两个皇后都不能处于同一行.同一列或同一斜线上. 二.算法思想 1.构建棋 ...