线段树专项练习


这个草稿存在于我的CSDN良久,最近一场div2的E题出现了一次线段树相关,所以开始填坑。
以下关于加法、乘法和根号线段树来自之前久远的某一天。


HH的项链
第二次做,20分钟切掉。但是因为有个快读…所以上网查了下但是发现了个假的快读模板最后三个test直接re(我也很疑惑啊…上了CF找了一些rank靠前的快读模版就ac了。

附上快读模版:

template <typename _T>
inline void read(_T &f) {f = 0; _T fu = 1; char c = getchar();while(c < '0' || c > '9') { if(c == '-') fu = -1; c = getchar(); }while(c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); }f *= fu;
}

AC代码


P1198 [JSOI2008]最大数
用Bit维护后缀区间上的最大值。
设置函数update用来将当前插入的值传入到儿子结点,设置函数query用来查询当前结点以及其所有的父结点拥有的最大的权值
这里的Bit与常见的前缀查询略有不同但是只要理解了本质也是个大水题。
AC代码


P2023 [AHOI2009]维护序列
裸的加法乘法线段树。
具体考虑可以参见之前暑训博客的线段树模版2
AC代码


补充一下根号线段树的处理办法:
SPOJ GSS4 (区间开根号 + 区间查询) (线段树)
线段树 从入门到进阶
具体的区间算法类似于普通的线段树。这里需要处理的问题是一个常数的优化,我们维护区间和与区间最大值两个量,显然,对于最大值为1的区间开根号已经无须修改了,而对于long long范围下的1e18开6次根号左右之后就可以得到1,从而整体的复杂度O(6NlogN)还算可以接受。
在Dijstra-Liu的博客中维护了区间的最大值与区间的最小值,同样也很显然的是,如果最大值开根号后与最小值开根号后的值相同,那么这一段区间可以直接用线段树进行修改而不需要单独考虑开根号后的取整问题。
两种优化办法其实本质类似,之后找到模版题的话可以实际操作一下。


UPDATED1: Vjudge NWU线段树练习

A 单点修改

B 区间置值 & 区间查询: 关键的变形就在于ststst和tagtagtag标记不是累加,而是直接覆盖为新值。

void down(int p, int l, int r){if(!tag[p]) return;st[ls] = tag[p] * (mid - l + 1); tag[ls] = tag[p];st[rs] = tag[p] * (r - mid); tag[rs] = tag[p];tag[p] = 0;
}

C
以线段树的存储结构进行的位运算。 对线段树分层,构造从节点ppp到其对应层数的映射,r后根据层数和输入nnn的奇偶性进行不同的位运算。

D 线段树区间合并

下午做的时候考虑了两种做法,一种是维护两个极值ST,分别记录每个点所对应的连续区间的左值和右值,不过这种做法在D的情况可以比较好地进行维护,在R的时候就比较麻烦了;另一种做法是二分求区间然后线段树区间置值,写起来也奇丑无比…

正确的办法是使用区间合并的办法。
开设结构体存储每个节点的左右端点序号、以左端点为起点的最长连续区间的长度、以右端点为终点的最长连续区间的长度以及该区间中最长连续区间的长度。

struct Tree{int l, r, ll, rr, all;
}tree[maxn << 2];

结合本题题意,需要做到单点修改、单点查询的操作。为此,我们给出如下变形的线段树操作办法:

//初始化区间线段树
void build(int p, int l, int r){tree[p].l = l; tree[p].r = r;tree[p].ll = tree[p].rr = tree[p].all = r - l + 1;if(r == l) return;build(ls, l, mid);build(rs, mid + 1, r);
}void up(int p){//更新连续左区间if(tree[ls].ll == tree[ls].r - tree[ls].l + 1) tree[p].ll = tree[ls].ll + tree[rs].ll;else tree[p].ll = tree[ls].ll;//更新连续右区间if(tree[rs].rr == tree[rs].r - tree[rs].l + 1) tree[p].rr = tree[ls].rr + tree[rs].rr;else tree[p].rr = tree[rs].rr;//更新全区间tree[p].all = max(tree[ls].all, max(tree[rs].all, tree[ls].rr + tree[rs].ll));
}//将x所在的元素置为k(k = 0/1);当前节点为p
void update(int p, int x, int k){if(tree[p].l == tree[p].r && tree[p].l == x){tree[p].all = tree[p].ll = tree[p].rr = k;return;}if(x <= (tree[p].l + tree[p].r) >> 1) update(ls, x, k);else update(rs, x, k);up(p);
}ll que(int p, int x){if(tree[p].l == tree[p].r) return tree[p].all;//x处于中心位置的区间则更新之if(x >= tree[ls].r - tree[ls].rr + 1 && x <= tree[rs].l + tree[rs].ll - 1)return tree[ls].rr + tree[rs].ll;//x处于左边其他某个位置else if(x < tree[ls].r - tree[ls].rr + 1) return que(ls, x);//x处于右边其他某个位置else return que(rs, x);
}

此外这道hdu 1540需要多组数据输入,并且题目没说这件事…

总而言之,区间合并的线段树算法是利用了线段树的存储结构,将存储空间上相邻的儿子节点上的区间信息高效地利用起来,快速完成某些信息的区间操作与查询。

摘自CSDN博主「sunyutian1998」的原创文章:

下面是做过的一些类型题总结

1 求一块满足条件的最左边的空白空间 poj3667

2 求某个元素所在连续段的长度(也可求左右端点) hdu1540

3 求某个连续段的起始位置 hdu2871

4 区间合并在扫描线求周长中的应用 hdu1828

5 区间合并与异或操作结合 以及求整个区间内最长连续段的长度 hdu3911 hdu3397

6 求区间最长连续上升序列 hdu3308

7 求最大子段和 uva1400

参考博客:
线段树区间合并小结 (言简意赅

BIT与线段树专项练习相关推荐

  1. 二逼平衡树——树套树(线段树套Splay平衡树)

    题面 Bzoj3196 解析 线段树和Splay两棵树套在一起,常数直逼inf,但最终侥幸过了 思路还是比较简单, 在原数组维护一个下标线段树,再在每一个线段树节点,维护一个对应区间的权值Splay. ...

  2. 线段树——HDU - 1698

    题目含义 就是初始化一堆数为1 可以经过操作把一个区间的数都改变 并求这堆数的总大小 题目分析 有一个 #include<iostream> #include<stdio.h> ...

  3. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  4. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

  5. [bzoj1582][Usaco2009 Hol]Holiday Painting 节日画画_线段树

    Holiday Painting 节日画画 bzoj-1582 Usaco-2009 Hol 题目大意:给定两个n*m的01网格图.q次操作,每次将第二个网格图的子矩阵全部变成0或1,问每一次操作后两 ...

  6. codefores 786B. Legacy(最短路,线段树优化拆点,好题)

    题目链接 B. Legacy time limit per test2 seconds memory limit per test256 megabytes inputstandard input o ...

  7. 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树

    题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...

  8. 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)

    题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...

  9. bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治

    这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节.. 点分治:时空复杂度$O(n\log^2n)$,常数巨大 主要就是3个堆的初始状态 C堆:每个节点一个,为子树中的点到它父亲的距离的堆. B ...

最新文章

  1. 在CentOS 6.9 x86_64上搭建全功能的OpenResty 1.13.6.1笔记
  2. hook 驱动 截屏
  3. JAVA基础知识(4)
  4. alxctools索引超出了数组界限_[译]V8中的数组类型
  5. i12蓝牙耳机使用说明书图片_飞利浦SHB4385 BASS+无线蓝牙耳机晒单 使用体验
  6. mysql 工时统计_有如下数据,要统计1月3号工时不足8小时的员工姓名及总工时,该sql语句该怎么写(用的mysql哈)...
  7. 职场潜规则:公司出现这三种信号,你必须果断辞职!
  8. Python3 多线程(连接池)操作MySQL插入数据
  9. linux mysql 相关操作、问题
  10. activemq linux 100M,Linux下安装 activemq 并指定jdk 1.8(示例代码)
  11. How to create a DXL attribute using a DXL script
  12. 小程序毕设作品之微信酒店预订小程序毕业设计(1)开发概要
  13. MATLAB画柱状图(包括普通柱状图,多组柱状图,三维柱状图)
  14. openbmc开发29:开关机管理
  15. Python 3.8 官网文档(中文版附下载)
  16. 网站漏洞修复之metinfo SQL注入漏洞
  17. 时间转换中的夏时制问题
  18. a eraser eraser还是an_an. eraser是什么意思
  19. 牛客网项目——前置技术(八):Kafka
  20. 课后练习03---126字母邮箱注册功能

热门文章

  1. JAVA的一些小知识点
  2. Unity中实现UI描边
  3. python爬虫爬取百度贴吧图片,requests方法
  4. 李小龙游戏java_java编程定义一个学生类Student,成员变量有学号,姓名,性别,身高,体重,平均分成绩;生成10个St...
  5. 泼辣修图专业版 Polarr Photo Editor 5.4.9 中文特别版 Mac 强大易用的修图工具
  6. CFileDialog简单使用
  7. 为什么卸载手机微软必应浏览器
  8. SAS实验四 一元回归分析
  9. 9个常用的Shell脚本
  10. MobaXterm解除会话数量限制(升级为专业版)