CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换)


  首先一共有四个操作,第一个和第四个都是线段树的基本操作,直接用线段树实现。
  
  第二个和第三个操作都是在分成 2k2 ^ k2k 长度区间操作,并且题目中的序列一共有 2n2^n2n 个节点,如果放到线段树里正好是 n+1n+1n+1 层,每层都由 2k2 ^ k2k 长度区间构成。第 000 层为叶子节点,第 nnn 层为根节点
  
  对于第三个操作 swapswapswap :相当于交换线段树两个相邻且长度为 2k2^k2k 的区间,由于本题一共有 p=1e5p = 1e5p=1e5 个修改查询操作,所以如果每次修改都修改的话哪怕是线段树也一定会超时。因此我们可以取巧,不真正地进行修改,而是每次查询或者修改单点操作的时候,根据修改标记来访问到相邻的区间。也就是相当于想要访问该节点的左(右)子树时候,由于区间翻转了,我们直接访问另一个右(左)子树区间即可。可以用一个变量来记录以下是否需要改变访问的左右结点。比如当前swapswapswap的是第 kkk 层 ,那么只需要标记第 k+1k + 1k+1 层,这样我们访问到该节点的第 k+1k + 1k+1层的时候,根据标记的指引就会跳转到第kkk层的相邻区间,满足题意。
  
  第二个同理,区间翻转我们参考文艺平衡树这道题,想要实现区间翻转,只需要把区间里的所有左右子树全部交换即可。而左右子树正好都是相邻的区间,那么我们对整个区间都做一次类似操作三的标记即可。假如当前需要reversereversereverse第 kkk 层,因为线段树是一颗满二叉树,在我们寻找该区间的时候如果到达第kkk层的时候,该点的左右子树就表示整个要找的区间,我们需要将第 kkk 层以下的层全部翻转,也就是将000 ~ kkk 层的节点都打赏标记即可。
  
  具体细节看代码,是在线段树模板的基础之上进行改进得到的。

这里有两个易错点:

  • 因为线段树翻转问题的解决办法是在翻转半区间打上标号,有标记的节点左右子树互换(实际体现就是查找的时候交换即可,整棵树实际上是不用动的),因此所有操作在寻找预定区间的时候就不能在根据当前根节点寻找预定区间,因为这里的p已经可能变了,就不能用 tr[p].ltr[p].ltr[p].l 和 tr[p].rtr[p].rtr[p].r 所以我们应该再传入参数 lll 和 rrr 来辅助寻找预定区间。
  • 凡是涉及到位运算的都要疯狂加括号!!!位运算的优先级实在是太糟糕了
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>typedef long long ll;
using namespace std;
const int N = 2000005;int n, m;
int a[N];
int rev[N], cnt;
struct tree{int l, r;ll sum;
}tr[N << 2];void pushup(int p)
{tr[p].sum = tr[p << 1].sum + tr[p << 1 | 1].sum;
}void build(int p, int l, int r)
{tr[p] = {l, r, 0};if(l == r){tr[p].sum = a[r];return ;}int mid = l + r >> 1;build(p << 1, l, mid);build(p << 1 | 1, mid + 1, r);pushup(p);
}void modify(int l, int r, int p, int x, int val, int depth)
{if(l == r){tr[p].sum = val;return ;}int mid = l + r >> 1;if(x <= mid)modify(l, mid, (p << 1) + (rev[depth] == 1), x, val, depth - 1);else modify(mid + 1, r, (p << 1 | 1) - (rev[depth] == 1), x, val, depth - 1);pushup(p);
}ll query(int rl, int rr, int p, int l, int r, int depth)
{if(rl >= l && rr <= r)return tr[p].sum;int mid = rl +rr >> 1;ll ans = 0;if(l <= mid)ans += query(rl, mid, (p << 1) + (rev[depth] == 1), l, r, depth - 1);if(r > mid)ans += query(mid + 1, rr, (p << 1 | 1) - (rev[depth] == 1), l, r, depth - 1);return ans ;
}int main()
{scanf("%d%d", &n, &m);for(int i = 1; i <= (1 << n); ++ i)scanf("%d", &a[i]);build(1, 1, 1 << n);while(m -- ){int op, x, y;scanf("%d%d", &op, &x);if(op == 1){scanf("%d", &y);modify(1, 1 << n, 1, x, y, n);// 2^n 个节点, 线段树一共会有n+1层第0层为叶子节点,第n层为根节点}else if(op == 2)for(int i = 0; i <= x; ++ i)rev[i] ^= 1;else if(op == 3)rev[x + 1] ^= 1;else {scanf("%d", &y);printf("%lld\n", query(1, 1 << n, 1, x, y, n));}}return 0;
}

CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换,清晰易懂)相关推荐

  1. Codeforces 1004F Sonya and Bitwise OR (线段树)

    题目链接 https://codeforces.com/contest/1004/problem/F 题解 这种水题都不会做了怎么.. 考虑一个序列的前缀 \(\text{or}\) 值只会变化 \( ...

  2. 线段树2 求区间最小值

    线段树2 求区间最小值 递归,DFS,尤其是二叉树,我只要知道我的返回节点就好,因为DFS的顺序一定是一样的,不同的题目和数据范围也是一样的,只是返回节点让DFS的深度不同. 递归的内容只有两部分:1 ...

  3. HDU 1166 敌兵布阵(线段树:点更新,区间求和)

    HDU 1166 敌兵布阵(线段树:点更新,区间求和) http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意: 给你n个整数,然后给你多条命令,每条命令如 ...

  4. Educational Codeforces Round 73 (Rated for Div. 2) F. Choose a Square 线段树 + 二维转一维

    传送门 文章目录 题意: 思路: 题意: 给你nnn个点(xi,yi)(x_i,y_i)(xi​,yi​),每个点有个价值cic_ici​,现在你可以框一个正方形,要求左下角和右上角的坐标(x,y)( ...

  5. Codeforces Round #686 (Div. 3) F. Array Partition 二分 + 线段树

    传送门 文章目录 题意: 思路: 题意: 化简一下题意就是求满足max(1,x)=min(x+1,y)=max(y+1,n)max(1,x)=min(x+1,y)=max(y+1,n)max(1,x) ...

  6. CodeForces - 1529E Trees of Tranquillity(贪心+线段树)

    题目链接:https://vjudge.net/problem/CodeForces-1529E 题目大意:给出两棵根节点为 111 的树,分别称为 AAA 树和 BBB 树,现在通过两棵树可以构造出 ...

  7. CodeForces - 1217F Forced Online Queries Problem(线段树分治+并查集撤销)

    题目链接:点击查看 题目大意:给出 nnn 个点,初始时互相不存在连边,需要执行 mmm 次操作,每次操作分为两种类型: 1xy1 \ x \ y1 x y:如果 (x,y)(x,y)(x,y) 之间 ...

  8. Codeforces 1045. A. Last chance(网络流 + 线段树优化建边)

    题意 给你 \(n\) 个武器,\(m\) 个敌人,问你最多消灭多少个敌人,并输出方案. 总共有三种武器. SQL 火箭 - 能消灭给你集合中的一个敌人 \(\sum |S| \le 100000\) ...

  9. AtCoder AGC001F Wide Swap (线段树、拓扑排序)

    题目链接: https://atcoder.jp/contests/agc001/tasks/agc001_f 题解: 先变成排列的逆,要求\(1\)的位置最小,其次\(2\)的位置最小,依次排下去( ...

最新文章

  1. iOS HitTest 机制
  2. 21天学通python pdf-21天学通Python PDF百度网盘资源下载
  3. vscode 导入第三方jar包(添加外部JAR)
  4. java ajax无刷分页_asp.net+ajax+json来实现无刷新分页功能
  5. 可视化应用实战案例:metacoder-相关进化树图的绘制
  6. poj1789(prim)
  7. DCMTK:定义信号灯,互斥锁和读/写锁的类
  8. Cent OS 6.4安装mysql
  9. ORACLE与PostgreSql的区别
  10. php升级语言,PHP是最好的语言,PHP 8.0带来了重大更新
  11. java package 路径_java文件路径问题及Eclipse package,source folder,folder区别及相互转换...
  12. uestc 方老师的分身 II
  13. 事实上,在你不知道的地方,还有一个世界杯!
  14. 每日一记:2017.7.20
  15. 【 软路由 】基于koolshare固件的软路由安装
  16. 小米、360、盛大路由器?居然还有这么多人趋之若鹜!!!想不通!
  17. MPSOC之8——启动及错误处理
  18. 四川大学计算机专业调剂,四川大学计算机学院(软件学院)2019考研调剂信息...
  19. CAD梦想画图中的“线型设置”
  20. (转)SQLSERVER智能提示插件-SQL PROMPT(9.4.6)的安装及注册流程

热门文章

  1. ICCV2021论文全汇总!附下载链接
  2. 深度理解目标检测(MMdetection)-HOOK机制
  3. linux系统资源监控
  4. 300 Longest Increasing Subsequence
  5. 根据status信息对MySQL服务器进行优化-2
  6. PHP如何进阶,提升自己
  7. 查询表中的所有字段名
  8. 改变从内部开始:开发者与管理者的协作
  9. Hobby开挂!加速web编码
  10. KTable的简单介绍