当前位置: 首页 > news >正文

题解:P10856 【MX-X2-T5】「Cfz Round 4」Xor-Forces

题解

首先,我们先考虑简单的情况,没有修改操作。

由题意得,一段区间颜色段个数可以转化为区间长度减去相邻同色个数,即区间 \([l,r]\) 的颜色段数为 \(r-l+1- \sum^r_{i=l+1}[a_i=a_{i-1}]\)

考虑线段树,那么一段区间所作的贡献即为左右两段区间的贡献之和,如果左子树右端和右子树左端相等,则减一,否则不做贡献。

void update(int rt){ans[rt]=ans[ls[rt]]+ans[rs[rt]]-(point[ls[rt]]r==point[rs[rt]].l);point[rt].l=point[ls[rt]].l,point[rt].r=point[rs[rt]].r;
}

接下来考虑修改操作,当异或到 \(x\) 的某一位为 \(1\) 时,我们就相当于将左右子树互换。

然后继续向下继续异或操作,由于异或具有交换律,我们只有在询问的时候考虑异或操作,修改直接 \(O(1)\) 即可。

但是,在查询时,每次都修改、打标记,就超时了!

注意到,\(x<n\),那么我们可以预处理,对于每一个答案提前求出来。

我们第 \(i\) 个答案可以通过 \(i-w\) 计算得出,其中 \(w\)\(i\) 的最高位。举个例子:

\(i\)01011 时,我们让它减去它最高位 01000 得到 00011,我们通过 00011 的线段树去更新 01011 的线段树。

我们不可能开 \(n\) 棵线段树,所以我们可以用可持久化线段树。

由于查询 \(m\) 次,每次查询一棵线段树,所以查询为 \(O(m \log n)\)。再来看预处理,我们一开始建树是 \(O(n)\) 的,接下来更新 \([1,n]\) 的答案,我们考虑每一个最高位 \(i\),那么它在 \([1,n]\) 中会出现 \(2^i\) 次,每次修改 \(\frac{n}{2^{i+1}}\) 个点,所以修改为 \(O(\sum_{i=0}^{k-1}2^i \times \frac{n}{2^{i+1}})\),即 \(O(n \log n)\)。综上,时间复杂度为 \(O(n \log n+m\log n)\)

Code

#include <bits/stdc++.h>
#define int long long
using namespace std;
int T, k, q, n, a[300005], rt[300005], cnt, op, l, r, x, lastans, w;
struct SegTree {int ls[300005 << 5], rs[300005 << 5], ans[300005 << 5];struct node {int l, r;} point[300005 << 5];  //记录每个节点左右两端的节点void update(int rt) {ans[rt] = ans[ls[rt]] + ans[rs[rt]] - (point[ls[rt]].r == point[rs[rt]].l);point[rt].l = point[ls[rt]].l, point[rt].r = point[rs[rt]].r;}void build(int &rt, int l, int r) {if (!rt)rt = ++cnt;if (l == r)return ans[rt] = 1, point[rt] = { a[l], a[r] }, void();int mid = l + r >> 1;build(ls[rt], l, mid), build(rs[rt], mid + 1, r);update(rt);}void change(int &rt1, int rt2, int l, int r, int x) {rt1 = ++cnt, ls[rt1] = ls[rt2], rs[rt1] = rs[rt2], ans[rt1] = ans[rt2], point[rt1] = point[rt2];if (r - l + 1 == (1 << x))swap(ls[rt1], rs[rt1]);else {int mid = l + r >> 1;change(ls[rt1], ls[rt2], l, mid, x), change(rs[rt1], rs[rt2], mid + 1, r, x);}update(rt1);}int query(int rt, int l, int r, int L, int R) {if (l == L && r == R)return ans[rt];int mid = l + r >> 1;if (R <= mid)return query(ls[rt], l, mid, L, R);else if (mid + 1 <= L)return query(rs[rt], mid + 1, r, L, R);elsereturn query(ls[rt], l, mid, L, mid) + query(rs[rt], mid + 1, r, mid + 1, R) -(point[ls[rt]].r == point[rs[rt]].l);}
} tree;
signed main() {scanf("%lld%lld%lld", &T, &k, &q), n = (1 << k);for (int i = 0; i < n; i++) scanf("%lld", &a[i]);tree.build(rt[0], 0, n - 1);for (int i = 1, j = k; i < n; i++, j = k) {while (!((i >> j) & 1)) j--;                              //求最高位tree.change(rt[i], rt[(i ^ (1 << j))], 0, n - 1, j + 1);  //注意j+1}while (q--) {scanf("%lld", &op);if (op == 1)scanf("%lld", &x), x = (x ^ (T * lastans)), w = (w ^ x);else {scanf("%lld%lld", &l, &r), l = (l ^ (T * lastans)), r = (r ^ (T * lastans));if (l > r)swap(l, r);printf("%lld\n", lastans = tree.query(rt[w], 0, n - 1, l, r));}}return 0;
}
http://www.jsqmd.com/news/35892/

相关文章:

  • python: Virtualenv的安装与应用
  • 题解:AT_abc147_f [ABC147F] Sum Difference
  • 20231326《密码系统设计》第八周预习报告
  • PERL Docker 容器化部署指南
  • 解放双手!使用Roslyn生成代码让你的 HTTP 客户端开发变得如此简单
  • pandoc用法
  • JMeter:性能测试利器全解析 - 实践
  • 251109
  • electron-vite为linux打包成功,但是安装后运行无反应
  • 20231427田泽航第八周预习报告
  • 吐血推荐!6款超好用的AI论文写作工具
  • 完整教程:金蝶云星瀚 | 生产制造成本核算终极实操手册(从0到1,含两套完整案例)
  • 实用指南:TensorFlow2 Python深度学习 - TensorFlow2框架入门 - 自动微分和梯度
  • 浏览器Blockstack.org全名字段输入限制缺失漏洞分析
  • 2025年维修厂家推荐排行榜单:行业权威解析
  • 2025年维修厂家口碑排行榜:专业制冷服务首选
  • 行业内专业的维修厂家功能亮点
  • 第四天 linux命令整理汇总
  • Dask-权威指南-全-
  • WGCLOUD磁盘告警有没有恢复通知
  • 疑似 CSP-SB、CSP-JB、NOSb 考题泄露
  • 人工智能团队的技术工具
  • C++之开始学习C++(二) - Invinc
  • 如何禁止谷歌浏览器更新提示
  • Azure-Arc-支持的面向多云的-Kubernetes-指南-全-
  • 拓扑 AC 2025 线上 NOIP 联测 #2
  • 04--CSS基础(3) - 指南
  • P14462 【MX-S10-T3】『FeOI-4』寻宝游戏
  • 完整教程:FocusAny 发布v1.1.0 插件搜索过滤,FAD文件优化,插件显示MCP服务
  • 11.9 模拟赛 T3