对本题的评价:有思维含量的线段树好题。曲子好听,曲绘好看,曲师人品好,谱子写得好,鸠好看

题解: 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求:

\[(\sum_{i=l}^r\bigcup_{j=l}^iA_j ) \bmod 2^{30}
\]

其中 \(\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 题解的更多相关文章

  1. LuoguP7127 「RdOI R1」一次函数(function) 题解

    Content 设 \(S_k\) 为直线 \(f(x)=kx+k-1\),直线 \(f(x)=(k+1)x+k\) 与 \(x\) 轴围成的三角形的面积.现在给出 \(t\) 组询问,每组询问给定一 ...

  2. 「POI2011 R1」Conspiracy

    「POI2011 R1」Conspiracy 解题思路 : 问题转化为,将点集分成两部分,其中一部分恰好组成一个团,其中另一部分恰好组成一个独立集. 观察发现,如果求出了一个解,那么答案最多可以在这个 ...

  3. LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)

    题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...

  4. LOJ #2540. 「PKUWC 2018」随机算法(概率dp)

    题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...

  5. Note -「动态 DP」学习笔记

    目录 「CF 750E」New Year and Old Subsequence 「洛谷 P4719」「模板」"动态 DP" & 动态树分治 「洛谷 P6021」洪水 「S ...

  6. 「AHOI / HNOI2017」影魔

    「AHOI / HNOI2017」影魔 题目描述 解决这类比较复杂的区间贡献问题关键在于找到计算的对象. 比如这道题,我们计算的对象就是区间中间的最大值. 对于点\(i\),我们找到左边第一个比他大的 ...

  7. 「GXOI / GZOI2019」简要题解

    「GXOI / GZOI2019」简要题解 LOJ#3083. 「GXOI / GZOI2019」与或和 https://loj.ac/problem/3083 题意:求一个矩阵的所有子矩阵的与和 和 ...

  8. [LOJ 2022]「AHOI / HNOI2017」队长快跑

    [LOJ 2022]「AHOI / HNOI2017」队长快跑 链接 链接 题解 不难看出,除了影响到起点和终点的射线以外,射线的角度没有意义,因为如果一定要从该射线的射出一侧过去,必然会撞到射线 因 ...

  9. 「国家集训队」小Z的袜子

    「国家集训队」小Z的袜子 传送门 莫队板子题. 注意计算答案的时候,由于分子分母都要除以2,所以可以直接约掉,这样在开桶算的时候也方便一些. 参考代码: #include <algorithm& ...

  10. P7708「Wdsr-2.7」八云蓝自动机 Ⅰ

    *X. P7708「Wdsr-2.7」八云蓝自动机 Ⅰ. 摘自 分治与根号数据结构学习笔记 第三部分 莫队 例题 X.. 一道莫队好题.私以为本题最有价值的地方在于对单点修改的转化以及对交换两个数的处 ...

随机推荐

  1. 更换Linux系统镜像源

    更换Linux系统镜像源 切换镜像源通常是为了提高软件包下载的速度和稳定性.以下是CentOS 7切换镜像源的一般步骤: 一.安装wget(如果尚未安装) 首先,需要确保系统中安装了wget工具,因为 ...

  2. Layer子域名挖掘机

    Layer子域名挖掘机 Layer子域名挖掘机是一款功能强大的域名查询工具,主要用于提供网站子域名的查询服务. 域名与子域名 域名 域名,又称网域,是互联网上用于标识特定计算机或计算机组的一串由点分隔 ...

  3. 配置Slf4j

    1.maven添加 <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api< ...

  4. 项目中途引入Mybatis-plus后报错,报错Caused by: java.lang.ClassNotFoundException: org.mybatis.logging.LoggerFactory

    一.报错原因 mybatis-plus和pagehelper jar包冲突,注释mybatis-spring和pagehelper插件即可 <!-- SpringBoot集成mybatis框架 ...

  5. Hetao P1184 宝可梦训练家 [ 绿 ][ 背包dp ][ 线性dp ]

    原题 题解 一道超级牛逼的背包变形,想通之后真的很简单,难点在于想到使用 dp 并且用 dp 的值判断是否合法. 首先观察本题的数据范围:\(1\le n,q \le 10^5\) ,可知本题的询问要 ...

  6. WPF DataTemplate DataContext 绑定问题

    当使用DataTemplate时,需要用数据绑定,设置数据绑定的方式可参考: https://supportcenter.devexpress.com/ticket/details/t736087/d ...

  7. 使用Bioaider进行本地blast

    系统环境为windows11 1. 下载blast程序 https://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/LATEST/ 双击安装,记住自己的 ...

  8. Nginx - [02] 安装部署&配置

    官网下载地址:http://nginx.org/en/download.html 001 || 安装[windows] 解压之后,在命令提示符窗口启动nginx.exe 在浏览器访问80端口:loca ...

  9. K8s - 容器编排引擎Kubernetes

    什么是Kubernetes? 背景 Kubernetes 是开源的容器集群管理项目,诞生于2014年,由Google公司发起 前身Borg系统在Google内部应用了十几年,积累了大量来自生产环境的实 ...

  10. luogu-P3343题解

    简要题意 给定一张 \(n\) 个点 \(m\) 条边的图,边的边权是 \([0, 1]\) 之间均匀分布的随机实数,且相互独立.求最小生成树的最大边权的期望值. 思路 首先有一个比较神秘的跟概率有关 ...