【线段树】【P3372】模板-线段树
Definition&Solution
线段树是一种log级别的树形结构,可以处理区间修改以及区间查询问题。期望情况下,复杂度为O(nlogn)。
核心思想见百度百科,线段树即将每个线段分成左右两个线段做左右子树。一个线段没有子树,当且仅当线段表示的区间为[a,a]。
由于编号为k的节点的子节点为2k以及2k+1,线段树可以快速的递归左右叶节点。
lazy标记:当进行区间修改的时候,如果一个区间整体全部被包含于要修改的区间,则可以将该区间的值修改后,将lazy标记打在区间上,不再递归左右区间。
例如,要修改[15,30]区间整体+2,当前区间为[16,24],被包含于要修改的区间。记代表区间[16,24]的节点编号为k,则tree[k]+=2*(24-16+1),同时lazy[k]+=2。
在下次修改或查询到k节点时,进行lazy的下放,即如下代码
inline void Free(cl l,cl r,cl p) { ll m=(l+r)>>,dp=p<<; tree[dp]+=(m-l+)*lazy[p];tree[dp+]+=(r-m)*lazy[p]; lazy[dp]+=lazy[p];lazy[dp+]+=lazy[p]; lazy[p]=; }
注意:被打上lazy标记的区间实际上已经修改完区间和,每次free修改的是子区间。
Example
Description
已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.求出某区间每一个数的和
Input
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和
Output
输出包含若干行整数,即为所有操作2的结果。
Sample Input
Sample Output
Hint
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
Solution
模板题。有一些需要注意的地方会在summary写明
Code
#include<cstdio> #define maxn 100010 #define maxt 400010 #define ll long long int #define cl const long long int inline void qr(long long &x) { ; ') { ; ch=getchar(); } )+(x<<)+(ch^),ch=getchar(); x*=f; return; } inline long long max(const long long &a,const long long &b) {if(a>b) return a;else return b;} inline long long min(const long long &a,const long long &b) {if(a<b) return a;else return b;} inline ) return x;else return -x;} inline void swap(long long &a,long long &b) { long long c=a;a=b;b=c;return; } ll n,m,MU[maxn],sign,a,b,c; ll tree[maxt],lazy[maxt]; void build(const ll l,const ll r,const ll p) { if(l>r) return; if(l==r) {tree[p]=MU[l];return;} ll m=(l+r)>>,dp=p<<; build(l,m,dp);build(m+,r,dp+); tree[p]=tree[dp]+tree[dp+]; } inline void Free(cl l,cl r,cl p) { ll m=(l+r)>>,dp=p<<; tree[dp]+=(m-l+)*lazy[p];tree[dp+]+=(r-m)*lazy[p]; lazy[dp]+=lazy[p];lazy[dp+]+=lazy[p]; lazy[p]=; } inline )*v;lazy[p]+=v;} void add(cl l,cl r,cl p,cl aiml,cl aimr,cl v) { if(l>r) return; if(l>aimr||r<aiml) {return;} if(l>=aiml&&r<=aimr) {wohenlan(l,r,p,v);return;} Free(l,r,p); ll m=(l+r)>>,dp=p<<; add(l,m,dp,aiml,aimr,v);add(m+,r,dp+,aiml,aimr,v); tree[p]=tree[dp]+tree[dp+]; } ll ask(cl l,cl r,cl p,cl aiml,cl aimr) { ; ;} if(l>=aiml&&r<=aimr) {return tree[p];} Free(l,r,p); ll m=(l+r)>>,dp=p<<; ,r,dp+,aiml,aimr); } int main() { qr(n);qr(m); ;i<=n;++i) qr(MU[i]); build(1ll,n,1ll); while(m--) { sign=a=b=;qr(sign);qr(a);qr(b); ) { c=;qr(c); add(,n,,a,b,c); } , n, , a, b)); } ; }
Summary
1、线段树大小要开4*n。理论上线段树会有2*n个子节点,但是试试这棵线段树:1 2 3 4 5
如图所示:
可以看到,节点数确实是6*2-1=11个,但是由于我们每个节点编号都严格按照母节点*2(+1)进行编号,所以我们的编号开到了2*n之外。开4*n是比较保险的。
2、注意对lazy标记的free操作要在确定区间可以再分以后进行。即先写
if(l>=aiml&&r<=aimr) {wohenlan(l,r,p,v);return;}
或
if(l>=aiml&&r<=aimr) {return tree[p];}
后,如果没有return,则证明区间一定是可再分的,即还没有递归到叶节点,这时才可以进行free操作。否则的话考虑在叶节点的编号可能大于2*n,我们在叶节点free了一下,标记被下放到了4*n以外……
然后你就炸了。
【线段树】【P3372】模板-线段树的更多相关文章
- 【数据结构与算法】Trie(前缀树)模板和例题
Trie 树的模板 Trie 树的简介 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树.他的核心思想是空间换 ...
- hdu 1754 I Hate It (模板线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=1754 I Hate It Time Limit: 9000/3000 MS (Java/Others) M ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- LuoguP3834 【模板】可持久化线段树 1(主席树)|| 离散化
题目:[模板]可持久化线段树 1(主席树) 不知道说啥. #include<cstdio> #include<cstring> #include<iostream> ...
- 【洛谷P3834】(模板)可持久化线段树 1(主席树)
[模板]可持久化线段树 1(主席树) https://www.luogu.org/problemnew/show/P3834 主席树支持历史查询,空间复杂度为O(nlogn),需要动态开点 本题用一个 ...
- Pascal 线段树 lazy-tag 模板
先说下我的代码风格(很丑,勿喷) maxn表示最大空间的四倍 tree数组表示求和的线段树 delta表示增减的增量标记 sign表示覆盖的标记 delta,sign实际上都是lazy标志 pushd ...
- 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...
- 洛谷P3834 [模板]可持久化线段树1(主席树) [主席树]
题目传送门 可持久化线段树1(主席树) 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定 ...
随机推荐
- Android Studio怎样创建App项目
然后等待大约N分钟: 默认的是Android模式, 改为Project模式更符合我们的习惯:
- leetcode个人题解——#22 Generate Parentheses
思路: 递归解决,如果左括号个数小于右括号或者左括号数小于总括号对数,则生成一个左括号,如果左括号数大于右括号,生成一个右括号. class Solution { public: vector< ...
- 百度编辑器ueditor的图片地址修正
我用的百度编辑器为1.4.2的,相对于现在这个时间来说是比较新的.之前去的1.3版的,后来更新到1.4之后出现路径问题.因为今天晚上出现特别奇怪的问题,所以特地又整了一遍,发现这玩意还是得自己弄通了好 ...
- matlab 直方图均衡化(含rgb)
步骤: 统计原图像素每个像素的个数 统计原图像<每个灰度级的像素的累积个数 家里灰度级得映射规则 将原图每个像素点的灰度映射到新图 代码: clear all I=imread('1.jpg') ...
- 哈希表 STL map
计数排序时我们使用一个数组来记录出现的数字的次数,而当数据范围太大时,无法建立一个那么大地数组(而且可能空间利用率很低,太浪费),此时可以改用hash table . binary search tr ...
- 一个demo让你彻底理解Android中触摸事件的分发
注:本文涉及的demo的地址:https://github.com/absfree/TouchDispatch 1. 触摸动作及事件序列 (1)触摸事件的动作 触摸动作一共有三种:ACTION_DOW ...
- error LNK2019: 无法解析的外部符号 该符号在函数 中被引用 解决方案
需要添加lib或者dll库.项目-属性-配置属性-链接器-输入-附件依赖项,添加需要的lib. 例如我在运行OSG程序的时候,忘记添加了附件依赖项就会报这个错. 解决方案如图.
- bwapp之xss(blog)
存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行.这种XSS比较危险,容易造 ...
- 通过access_token openid获取微信用户昵称等信息
<?php header('Access-Control-Allow-Origin:*'); $access_token = !empty($_GET['access_token'])?$_GE ...
- Perfmon - Windows 自带系统监控工具
一. 简述 可以用于监视CPU使用率.内存使用率.硬盘读写速度.网络速度等. Perfmon提供了图表化的系统性能实时监视器.性能日志和警报管理,系统的性能日志可定义为二进制文件.文本文件.SQLSE ...