线段树

线段树(HDU 1754 I Hate It)

谁说胖子不能爱 提交于 2020-02-28 16:46:02
第一次写线段树,参考了一下别人的线段树代码 #define L(x) (x << 1) #define R(x) ((x << 1) | 1) code: #include <stdio.h> #define max(x,y) x>y?x:y const int MAX = 200005 ; struct Tree{ int left; int right; int data; }tr[MAX* 3 ]; int n,m,s[MAX],a,b; char cmd; void build( int l, int r, int pos){ tr[pos].left = l; tr[pos].right = r; if (l == r){ tr[pos].data = s[l]; return ; } int mid = (l + r) >> 1 ; build(l,mid,(pos<< 1 )); build(mid+ 1 ,r,(pos<< 1 )+ 1 ); tr[pos].data = max(tr[pos<< 1 ].data,tr[(pos<< 1 )+ 1 ].data); } void Update( int l, int r, int pos){ if (l == r){ tr[pos].data = b; return ; } int mid = (l + r) >>

线段树--从入门到入土

China☆狼群 提交于 2020-02-28 07:00:46
线段树,强大的数据结构,用处也是比较广的。 首先,我们要明白线段树是个啥? 线段树,线段嘛,有左右端点,那么它当然可以代表一个区间,那么区间上的好多事情都可以用它来搞,比如:区间加,区间乘,区间求和。 首先让我们先看个线段树的模型。 如图,这就是一棵线段树的模型。 圈内的点表示这是第几个点,红色表示这个点表示的区间范围。 每个点和它的左右两个儿子的编号是有一定的关系的: 点N,它的 左儿子编号为N$\times$2 , 右儿子编号为N$\times$2+1 . 线段树支持单点修改,区间修改,单点查询,区间查询。 讲解有易到难。 先放一张后边当例子讲解的图( 每个圈中的数表示的为这个区间的和 )。 构建线段树框架 假设一段长度为 N 的序列,那么我们需要维护总长为 1--N 的线段。 对于每一个点,我们需要确定它所表示的线段的 左端点 右端点 以及我们要维护的 区间和 对于每个点的左儿子和右儿子来说,左儿子继承前一半 [L,(L+R)/2],右儿子继承后一半( (L+R)/2,R ]。 还有我们维护的区间和,每个大区间都是有两个小区间组成,那么 大区间的和 = 左儿子的和+右儿子的和。 这部分代码: struct ahah{ long long l,r,sum,f;  //对于 f 的作用,后边会有解释,此处忽略。 }tree[200000<<2];    注意此处四倍空间。

算法笔记:带修主席树(树套树)

試著忘記壹切 提交于 2020-02-28 04:48:00
从我短暂的ACMer生涯当中学到一件事———越是玩弄数据结构,就越会发现树的能力是有极限的… 除非超越树。 那就再套一层树吧!Wryyyyy!!! 最近打算研究一波树套树,平衡树怎么套还没搞懂,目前学习了一点套主席树的方法,平衡树的内容可能也会补在这吧。 众所周知,主席树维护的是一种类似前缀和的结构,每个节点都是包含了之前所有节点值的权值线段树,通过继承上一个节点权值线段树的部分结构以减少大量的空间和时间。 因为维护的是前缀和的结构,因此主席树满足可减性,在解决如静态区间第k小等问题中只需要取区间右端的树减区间左端的树即可得到仅包含有区间内值的权值线段树,这其实就类似于求一个序列的某个区间和可以用前缀和数组,区间右端的值减区间左端的值得到。 当然,以上都是废话,会写主席树的话肯定也知道这些东西。不过我还是要写出来,是因为想展示主席树其实本身也是一种“数据结构套数据结构”的形式,把每个节点的权值线段树抽象成点,主席树的上层就是一个简单的前缀和数组,下层使用权值线段树代替了前缀和数组中的每一个位置。而带修主席树不外乎就是把这个上层结构更换了一下,换成树状数组或线段树之类的其它数据结构。 以下通过两个简单的板子题展示下如何使用树状数组套主席树( 其实应该是树状数组套权值线段树 洛谷 P2617 Dynamic Rankings 题意: 给一个含有n个数的序列,需要支持两种操作: 1

一文可能看懂扫描线

我们两清 提交于 2020-02-27 03:01:14
扫描线入门 本文的文字部分有些冗长,有些地方讲的也有些枯燥,但是笔者已经尽量让文字不那么晦涩,也加了一些配图,相信坚持看完的读者会有所收获 本文参考:https://blog.csdn.net/tomorrowtodie/article/details/52048323 矩形面积并 对于矩形 A , B A,B A , B ,它们的面积并就是 A ∪ B A \cup B A ∪ B 的面积,多个矩形的情况可以类比一下。有一种想法是拿所有矩形面积之和减去多加了的部分的面积,但是多加的部分并不好求,因为要计算交点,还要知道重复部分到底重复了多少次,那要怎么求矩形面积并呢?我们可以假想有一条与 x x x 轴平行的直线,从下往上扫,把面积并分割成多个部分,如下图所示,这样以来面积并就等于各个颜色的部分的面积之和,每个部分的高很容易求,只要把每个矩形的每个横向边(与 x x x 轴平行的边)的高度记录一下,排个序,做差就可以,关键在于怎么求每个部分的长度,这时,线段树又出场了(不知道线段树的话,这里是 传送门 ) 图片地址:https://blog.csdn.net/tomorrowtodie/article/details/52048323 区间信息 既然要用线段树,那线段树存什么?或者说要维护区间信息是什么?我们对横坐标区间建线段树, 根节点 的区间是 [ x m i n , x m

线段树入门

拈花ヽ惹草 提交于 2020-02-26 22:19:59
线段树入门 引题 有一个包含 N N N 个数的序列( N ≤ 1 e 6 N \leq 1e6 N ≤ 1 e 6 ),给 Q ( ≤ 1 e 6 ) Q(\le 1e6) Q ( ≤ 1 e 6 ) 个操作,每个操作是下面两种中的一种: 区间加:给定 l , r , x l,r,x l , r , x ,将序列 N N N 下标 ∈ [ l , r ] \in [l, r] ∈ [ l , r ] 的数加上 x x x 区间求和:给定 l , r l,r l , r ,询问下标 ∈ [ l , r ] \in [l,r] ∈ [ l , r ] 的数的和 一种很暴力的想法是对每个操作都一遍循环进行修改、求和,显然会超时;看到区间求和很容易就能想到前缀和,这样可以把区间求和降到常数复杂度,然而区间加还是 O ( N ) O(N) O ( N ) ;这时就需要线段树登场了 介绍 线段树是一种实用的数据结构,它可以快速地处理区间操作,维护区间信息。线段树是一棵二叉树,它的每一个节点存储的是一个区间的信息(如区间和, 左右端点等),如下图所示 笔者个人比较习惯用结构体来定义每一个节点,如果只开 2 N 2N 2 N 个节点,有一些情况是不够的,索性开到 4 N 4N 4 N ,并从上到下,从左向右进行编号,根节点编号为1,其左儿子是2,右儿子是3,一次类推: # define ls

poj 2104 K-th Number

杀马特。学长 韩版系。学妹 提交于 2020-02-26 22:08:37
Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 45283 Accepted: 15067 Case Time Limit: 2000MS Description You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment. That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?" For example,

线段树

穿精又带淫゛_ 提交于 2020-02-26 18:55:41
#include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rush! ios::sync_with_stdio(false);cin.tie(0); const int inf = 0x3f3f3f3f; const long long linf = 0x3f3f3f3f3f3f3f3f; const int maxn=100005; int tree[maxn<<2]; //线段树 int lz[maxn<<2]; //懒惰数组 void pushup(int rt) { tree[rt]=tree[rt<<1]+tree[rt<<1|1]; } void pushdown(int l,int r,int rt) { if(lz[rt]) { int m=(l+r)>>1; lz[rt<<1]+=lz[rt]; lz[rt<<1|1]+=lz[rt]; tree[rt<<1]+=(m-l+1)*lz[rt]; tree[rt<<1|1]+=(r-m)*lz[rt]; lz[rt]=0; } } void build(int l,int r,int rt) { if(l==r) { cin>>tree[rt]; return ; }

zkw线段树

◇◆丶佛笑我妖孽 提交于 2020-02-26 16:39:56
zkw-Segment Tree zkw线段树 Brief Introduction To be updated Algorithm To be updated Template Code #include <cstdio> #include <cstring> #define LL long long #define MAXN 100005 struct node{ LL sum,tag; }sgt[MAXN<<2]; int M; int a[MAXN]; void built(int n){ for(M=1;M<n+2;M<<=1); memset(sgt+M,0,M*sizeof(sgt[0])); for(int i=1;i<=n;i++) sgt[M+i].sum=a[i]; for(int i=M-1;i;i--) sgt[i].sum=sgt[i<<1].sum+sgt[i<<1|1].sum; } void modify(int l,int r,LL del){ LL len=1,lc=0,rc=0; for(l=l+M-1,r=r+M+1;l^r^1;l>>=1,r>>=1,len<<=1){ if(~l&1) sgt[l+1].tag+=del, lc+=len; if(r&1) sgt[r-1].tag+=del, rc+=len; sgt[l>>1]

文献阅读02-动态拼车服务中的高效插入操作

眉间皱痕 提交于 2020-02-24 04:57:28
题目:An Efficient Insertion Operator in Dynamic Ridesharing Services (动态拼车服务中的高效插入操作) 作者:Yi Xu (易旭), Yongxin Tong(童永新), Yexuan Shi(叶璇), Qian Tao(钱涛), Ke Xu(柯旭), Wei Li(魏丽) 单位:软件开发环境与环境国家重点实验室;北京航空航天大学北京大数据与脑计 算高级创新中心 研 究 领 域(想做 什么,功 能,应用 或 研 究 背景) 研究当前动态拼车在智能交通应用中的插入操作,改进当前当前插入操作。 针 对 的 问题(要 解 决 什 么 技 术 或 者 研 究问题) 动态拼车中的核心操作是插入操作。给定一个工作者和一条可行路线,其中包含先前 请求中的一系列起点-终点对,则插入操作将新请求的起点-终点对插入到当前路线, 从而优化某些目标。常见的优化目标包括最小化所有请求的最大等待时间/距离,最 小化总旅行时间/距离。但其时间复杂度为 O(n3),其中 n 为分配给工作者的所有请求 的数量。这个时间复杂度从根本上限制了基于城市规模的动态共享应用的效率。 解 决 方 法 的 思 路(总体 基 本 原 理,指出 创 新 之 处) 提出了一个基于分区的框架,将请求集 R+划分为四个不相交的集合,并独立地处理 它们的约束和目标值

文献阅读02-动态拼车服务中的高效插入操作

左心房为你撑大大i 提交于 2020-02-23 17:08:26
题目:An Efficient Insertion Operator in Dynamic Ridesharing Services (动态拼车服务中的高效插入操作) 作者:Yi Xu (易旭), Yongxin Tong(童永新), Yexuan Shi(叶璇), Qian Tao(钱涛), Ke Xu(柯旭), Wei Li(魏丽) 单位:软件开发环境与环境国家重点实验室;北京航空航天大学北京大数据与脑计 算高级创新中心 研 究 领 域(想做 什么,功 能,应用 或 研 究 背景) 研究当前动态拼车在智能交通应用中的插入操作,改进当前当前插入操作。 针 对 的 问题(要 解 决 什 么 技 术 或 者 研 究问题) 动态拼车中的核心操作是插入操作。给定一个工作者和一条可行路线,其中包含先前 请求中的一系列起点-终点对,则插入操作将新请求的起点-终点对插入到当前路线, 从而优化某些目标。常见的优化目标包括最小化所有请求的最大等待时间/距离,最 小化总旅行时间/距离。但其时间复杂度为 O(n3),其中 n 为分配给工作者的所有请求 的数量。这个时间复杂度从根本上限制了基于城市规模的动态共享应用的效率。 解 决 方 法 的 思 路(总体 基 本 原 理,指出 创 新 之 处) 提出了一个基于分区的框架,将请求集 R+划分为四个不相交的集合,并独立地处理 它们的约束和目标值