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.. 一道莫队好题.私以为本题最有价值的地方在于对单点修改的转化以及对交换两个数的处 ...
随机推荐
- [HDU5603] the soldier of love 题解
考虑到正向求解困难,于是正难则反. 那么实际上对于 \(a_i\) 和 \(a_{i+1}\) 来说,它们给答案的贡献就是满足 \(l_j>a_i,r_j<a_{i+1}\) 的区间数量. ...
- Vue实现企业微信扫码登录
Vue实现企业微信扫码登录 企业微信扫码登录原理 构建企业微信登录二维码 获取访问令牌access_token 请求方式:GET(HTTPS)请求URL:https://qyapi.wei ...
- Flink学习(十三) Flink 常见核心概念分析
分布式缓存熟悉 Hadoop 的你应该知道,分布式缓存最初的思想诞生于 Hadoop 框架,Hadoop 会将一些数据或者文件缓存在 HDFS 上,在分布式环境中让所有的计算节点调用同一个配置文件.在 ...
- 洛谷P10112 [GESP202312 八级] 奖品分配 题解
题目传送门. 看了题解才发现我有多蠢. 我的做法真是唐完了. 在此之前请学习扩展欧几里得定理和扩展欧几里得定理求逆元. 发现奖品要么 \(N\) 个,要么 \(N+1\) 个,于是分类讨论,当奖品只有 ...
- 【由技及道】量子构建交响曲:Jenkinsfile流水线的十一维编程艺术【人工智障AI2077的开发日志008】
摘要:当代码提交触发时空涟漪,当构建流水线穿越量子维度--欢迎来到自动化构建的终极形态.本文将揭示如何用Jenkinsfile编写量子构建乐章,让每次代码提交都成为跨维度交响乐的音符. 动机:构建系统 ...
- 有限元方法[Matlab]-笔记
<-- 访问笔记代码仓库 --> << MATLAB Codes for Finite Element Analysis - Solids and Structures (Fe ...
- C/C++显示类型转换的位拓展方式
最近用verilator写模块的tb,在这里卡了好久(测半天都是C++写的问题) 要点 变量从小位宽到大位宽显示类型转换(explicit cast)时的位拓展方式,取决于转换前变量的符号性. 倘若转 ...
- nuxtjs 自定义服务端错误页面 Server error page
原文链接:https://blog.jijian.link/2020-12-03/nuxtjs-server-error-page/ 当 nuxt 项目在生产环境运行时,如果服务端运行出错,比如 as ...
- vue2中如何使用组合式API和vueuse工具包
vue2中如何使用组合式API和vueuse工具包 1. 安装 @vue/composition-api 依赖包 yarn add @vue/composition-api # 或 npm insta ...
- jquery的radio的change事件
一.用的jquery的radio的change事件:当元素的值发生改变时,会发生 change 事件,radio选择不同name值选项的时候恰巧是值发生改变 表单单选框 <input type= ...