看了一下题解里的zkw线段树,感觉讲的不是很清楚啊(可能有清楚的但是我没翻到,望大佬勿怪)。

决定自己写一篇。。。希望大家能看明白。。。


zkw线段树是一种优秀的非递归线段树,速度比普通线段树快两道三倍,同时代码量不大。

(当然,存在很多线段树可做zkw不可做的题)

zkw线段树的核心思路就是先修改叶子,然后从底向上沿着路径修改。

如果画一张图出来整个过程有点像逐渐两条交回在根节点的链。


注意:对于需要维护的区间[1,n],zkw线段树维护的实际上是[0,n+1]。


建树

inline void build(ll n){
bit=1;
while(bit<n+2)bit<<=1;
for(ll i=1;i<=n;++i)tree[bit+i]=a[i];
for(ll i=bit-1;i>=1;--i)tree[i]=tree[i<<1]+tree[i<<1|1],tag[i]=0;
}

bit表示的底层的大小,我们需要先预处理出这个全局变量。

然后我们就可以先把叶子的值全部读入。

读入之后就顺着叶子向上走,更新上面的节点。

这一段代码没有什么复杂的地方。


更新

inline void update(ll l,ll r,ll val){
ll s,t,ln=0,rn=0,x=1;
for(s=bit+l-1,t=bit+r+1;s^t^1;s>>=1,t>>=1,x<<=1){
tree[s]+=val*ln,tree[t]+=val*rn;
if(~s&1)tag[s^1]+=val,tree[s^1]+=val*x,ln+=x;
if(t&1)tag[t^1]+=val,tree[t^1]+=val*x,rn+=x;
}
for(;s;s>>=1,t>>=1)tree[s]+=val*ln,tree[t]+=val*rn;
}

更新操作稍微比建树复杂一点。

s和t就是先前提到的两条链,当然准确地说,它们的轨迹才是那两条链。

ln,rn表示的是当前节点的长度(也就是s,t的长度)。

x表示的是s和t中间这一坨的长度。

然后也是一样的自底向上,每一次先更新两边,然后再判断该更新左儿子还是右儿子。


查询

inline ll query(ll l,ll r){
ll s,t,ln=0,rn=0,x=1,ans=0;
for(s=bit+l-1,t=bit+r+1;s^t^1;s>>=1,t>>=1,x<<=1){
if(tag[s])ans+=tag[s]*ln;
if(tag[t])ans+=tag[t]*rn;
if(~s&1)ans+=tree[s^1],ln+=x;
if(t&1)ans+=tree[t^1],rn+=x;
}
for(;s;s>>=1,t>>=1)ans+=tag[s]*ln,ans+=tag[t]*rn;
return ans;
}

查询操作和更新一样,没什么好讲的。


不开O2跑了511ms,比普通线段树的760+ms快很多(可能是我写丑了)

完整代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll N=100100;
ll n,m;
ll op,x,y,z;
ll a[N];
ll bit;
ll tree[N<<2],tag[N<<2];
inline void build(ll n){
bit=1;
while(bit<n+2)bit<<=1;
for(ll i=1;i<=n;++i)tree[bit+i]=a[i];
for(ll i=bit-1;i>=1;--i)tree[i]=tree[i<<1]+tree[i<<1|1],tag[i]=0;
}
inline void update(ll l,ll r,ll val){
ll s,t,ln=0,rn=0,x=1;
for(s=bit+l-1,t=bit+r+1;s^t^1;s>>=1,t>>=1,x<<=1){
tree[s]+=val*ln,tree[t]+=val*rn;
if(~s&1)tag[s^1]+=val,tree[s^1]+=val*x,ln+=x;
if(t&1)tag[t^1]+=val,tree[t^1]+=val*x,rn+=x;
}
for(;s;s>>=1,t>>=1)tree[s]+=val*ln,tree[t]+=val*rn;
}
inline ll query(ll l,ll r){
ll s,t,ln=0,rn=0,x=1,ans=0;
for(s=bit+l-1,t=bit+r+1;s^t^1;s>>=1,t>>=1,x<<=1){
if(tag[s])ans+=tag[s]*ln;
if(tag[t])ans+=tag[t]*rn;
if(~s&1)ans+=tree[s^1],ln+=x;
if(t&1)ans+=tree[t^1],rn+=x;
}
for(;s;s>>=1,t>>=1)ans+=tag[s]*ln,ans+=tag[t]*rn;
return ans;
}
int main(){
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;++i)scanf("%lld",&a[i]);
build(n);
while(m--){
scanf("%lld%lld%lld",&op,&x,&y);
if(op==1)scanf("%lld",&z),update(x,y,z);
else cout<<query(x,y)<<endl;
}
}

题解 P3372 【【模板】线段树1 】(zkw)的更多相关文章

  1. 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 ...

  2. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  3. 【线段树】【P3372】模板-线段树

    百度百科 Definition&Solution 线段树是一种log级别的树形结构,可以处理区间修改以及区间查询问题.期望情况下,复杂度为O(nlogn). 核心思想见百度百科,线段树即将每个 ...

  4. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  5. 线段树和zkw线段树

    作者作为一个蒟蒻,也是最近才自学了线段树,不对的地方欢迎大佬们评论,但是不要喷谢谢 好啦,我们就开始说说线段树吧 线段树是个支持区间操作和查询的东东,平时的话还是蛮实用的 下面以最基本的区间加以及查询 ...

  6. [NOIP10.6模拟赛]2.equation题解--DFS序+线段树

    题目链接: 咕 闲扯: 终于在集训中敲出正解(虽然与正解不完全相同),开心QAQ 首先比较巧,这题是\(Ebola\)出的一场模拟赛的一道题的树上强化版,当时还口胡出了那题的题解 然而考场上只得了86 ...

  7. 算法模板——线段树6(二维线段树:区域加法+区域求和)(求助phile)

    实现功能——对于一个N×M的方格,1:输入一个区域,将此区域全部值作加法:2:输入一个区域,求此区域全部值的和 其实和一维线段树同理,只是不知道为什么速度比想象的慢那么多,求解释...@acphile ...

  8. 【题解】Journeys(线段树优化连边)

    [#3073. Pa2011]Journeys (线段树优化连边) 这张图太直观了,直接讲透了线段树优化连边的原理和正确性. 考虑建立两颗线段树,一颗是外向树,一颗是内向树,相当于网络流建模一样,我们 ...

  9. Gorgeous Sequence 题解 (小清新线段树)

    这道题被学长称为“科幻题” 题面 事实上,并不是做法科幻,而是“为什么能这么做?”的解释非常科幻 换句话说,复杂度分析灰常诡异以至于吉如一大佬当场吃书 线段树维护的量:区间和sum,区间最大值max1 ...

  10. 洛谷题解P4314CPU监控--线段树

    题目链接 https://www.luogu.org/problemnew/show/P4314 https://www.lydsy.com/JudgeOnline/problem.php?id=30 ...

随机推荐

  1. 使用面向对象技术创建高级 Web 应用程序

    作者: 出处: 使用面向对象技术创建高级 Web 应用程序 来源:开源中国社区 作者:oschina 最近,我面试了一位具有5年Web应用开发经验的软件开发人员.她有4年半的JavaScript编程经 ...

  2. python--(常用模块-3-正则表达式)

    python--(常用模块-3-正则表达式) 正则表达式是对字符串操作的⼀种逻辑公式. 我们⼀般使⽤正则表达式对字符串进⾏匹 配和过滤. 使⽤正则的优缺点: 优点: 灵活, 功能性强, 逻辑性强. 缺 ...

  3. 在Vue中使用了Swiper ,动态从后台获取数据的之后,swiper滑动失效??

    在Vue中使用了Swiper ,动态从后台获取数据的之后,swiper滑动失效?? 是因为swiper提前初始化了,那时候数据还没有完全出来.这里有两种解决办法 1. 使用vue提供的$nextTic ...

  4. 修改UTC时间

    /sbin/hwclock --systohc date按照时间修正.

  5. BZOJ——1787: [Ahoi2008]Meet 紧急集合

    http://www.lydsy.com/JudgeOnline/problem.php?id=1787 题目描述 输入 输出 样例输入 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 ...

  6. 洛谷 P2111 考场奇遇

    P2111 考场奇遇 题目背景 本市的某神校里有一个学霸,他的名字叫小明(为了保护主人公的隐私,他的名字都用“小明”代替).在这次的期中考试中,小明同学走桃花运,在考场上认识了一位女生,她的名字叫小红 ...

  7. Android Material Design-Getting Started(入门)-(一)

    转载请注明出处:http://blog.csdn.net/bbld_/article/details/40400343 翻译自:http://developer.android.com/trainin ...

  8. 安卓APP载入HTML5页面解决方式总结

    因为H5页面在移动端的兼容性及扩展性方面体现出来的优势,又兼得APP中植入H5页面相应用的灵活性有大大的提升(如活动.游戏的更新等).APP开发不可避免的须要载入一些H5页面.但安卓client对网页 ...

  9. Unity3D——加入剑痕效果(PocketRPG Trail插件)

    首先非常感谢大家的支持,因为近期项目吃紧,所以更新的速度可能会有点慢!希望大家谅解,当然大家的支持是我最大的动力.我也会尽我所能写出更好的文章,当然因为本人是个新手并且工作的内容也不是unity3D. ...

  10. Windows下本机简易监控系统搭建(Telegraf+Influxdb+Grafana)--转

    原文地址:http://www.cnblogs.com/liugh/p/6683488.html 一.文件准备 1.1 文件名称 telegraf-1.2.1_windows_amd64.zip in ...