zoukankan      html  css  js  c++  java
  • 线段树lazytag优化模板

    线段树嘛。。。很基本的一种数据结构啦

    lazytag优化能不错的提高效率

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAX=1000000;
     4 struct pr {
     5     int sum;
     6     int lazy;
     7     int left,right;
     8 }tr[MAX+10];
     9 int n;
    10 inline int ll(int k) {return 2*k;}
    11 inline int rr(int k) {return 2*k+1;}
    12 inline int mid(int kk1,int kk2) {return (kk1+kk2)>>1;}
    13 void pushdown(int k) {
    14     if (tr[k].lazy) {
    15         tr[ll(k)].sum=tr[k].lazy*(tr[ll(k)].right-tr[ll(k)].left+1);
    16         tr[rr(k)].sum=tr[k].lazy*(tr[rr(k)].right-tr[rr(k)].left+1);
    17         tr[ll(k)].lazy=tr[rr(k)].lazy=tr[k].lazy;
    18         tr[k].lazy=0;
    19     }
    20 }
    21 
    22 void build(int k,int s,int t) {
    23     tr[k].left=s;tr[k].right=t;
    24     if(s==t) {tr[k].sum=1;return;}
    25     build(ll(k),s,mid(s,t));
    26     build(rr(k),mid(s,t)+1,t);
    27     tr[k].sum=tr[ll(k)].sum+tr[rr(k)].sum;
    28 }
    29 
    30 void modify(int k,int s,int t,int x) {
    31     int l=tr[k].left,r=tr[k].right;
    32     if(t<l||r<s) {
    33         tr[k].lazy=x;
    34         tr[k].sum=x*(r-l+1);
    35         return ;
    36     }
    37     pushdown(k);
    38     int mi=mid(l,r);
    39     if(t<=mi) modify(ll(k),s,t,x);
    40     else if(s>mi) modify(rr(k),s,t,x);
    41     else {
    42         modify(ll(k),s,mi,x);
    43         modify(rr(k),mi+1,t,x);
    44     }
    45     tr[k].sum=tr[ll(k)].sum+tr[rr(k)].sum;
    46 }
    47 int query(int k,int s,int t) {
    48     int l=tr[k].left,r=tr[k].right;
    49     if(l==s&&r==t) return tr[k].sum;
    50     pushdown(k);
    51     int mi=mid(l,r);
    52     int res=0;
    53     if (t<=mi) res+=query(ll(k),s,t);
    54     else if(s>mi) res+=query(rr(k),s,t);
    55     else res+=query(ll(k),s,mi)+query(rr(k),mi+1,t);
    56     return res;
    57 }
    View Code

    我的代码风格可能有点丑,请各位看官别介意

    具体可以参见这里

    下面简单来介绍下Lazytag思想:

    什么是LazyTag?线段树要修改很多次,但是很多次修改的值并没有被用到,这几次修改就是无用的,那么我们通过加一个lazy变量,记录当前需要往下传递的数值,待有用时再继续往下传递,这就是LazyTag思想。向下传递可见我的代码pushdown();

    介绍Lazy思想:lazy-tag思想,记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。

    ——yicbs

    在此通俗的解释我理解的Lazy意思,比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,它的节点标记为rt,这时tree[rt].l == a && tree[rt].r == b 这时我们可以一步更新此时rt节点的sum[rt]的值,sum[rt] += c * (tree[rt].r - tree[rt].l + 1),注意关键的时刻来了,如果此时按照常规的线段树的update操作,这时候还应该更新rt子节点的sum[]值,而Lazy思想恰恰是暂时不更新rt子节点的sum[]值,到此就return,直到下次需要用到rt子节点的值的时候才去更新,这样避免许多可能无用的操作,从而节省时间 。

    ——yicbs

    读者只要理解了这几句话,就理解了lazytag的精髓,然后即可套用模板,本模板实现了更新、查询操作。

    这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
  • 相关阅读:
    PHP之get请求用php脚本实现
    PHP之download
    PHP之缩略图
    PHP之upload
    文本域<textarea>将 替换成换行
    JSON中获取变量key的值
    emap表格checkbox属性默认勾选
    读取ORACLE数据库中BOLB形式数据在前端预览
    oracle常用语法
    批量删除本地仓库未下载完成的jar文件
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/segmenttree.html
Copyright © 2011-2022 走看看