• 线段树——模板


    洛谷P3372

    线段树支持区间修改和区间查询,以v变量表示当前一段区间的总值,tag为懒标记,记录修改操作,在查询子节点时,由父节点下传,记录修改值的大小,并在子节点加入懒标记

    l和r分别表示当前节点所包含的最左区间端点和最右区间端点,ls和rs分别代表当前节点的左子树和右子树

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<math.h>
      6 #define ll long long
      7 using namespace std;
      8 
      9 const ll maxn=1e5+10;
     10 ll n,m;
     11 ll a[maxn];
     12 
     13 struct node
     14 {
     15     ll v,tag;//权值与懒标记
     16     ll l,r;//左右两个端点
     17     node *ls,*rs;//左右两个子树
     18     
     19     inline void maketag(ll w)//修改节点值,打懒标记
     20     {
     21         v+=(r-l+1)*w;
     22         tag+=w;
     23     }
     24     inline void pushup()//权值上传(由子节点更新父节点)
     25     {
     26         v=ls->v+rs->v;
     27     }
     28     inline void pushdown()//下传(由父节点更新子节点)
     29     {
     30         if(tag==0) return ;
     31         else
     32         {
     33             if(ls==NULL)//无左子树
     34             {
     35                 node(l,(l+r)>>1);//动态开点
     36             }
     37             if(rs==NULL)//无右子树
     38             {
     39                 node(((l+r)>>1)+1,r);//动态开点
     40             }
     41             ls->maketag(tag);
     42             rs->maketag(tag);
     43             tag=0;
     44         }
     45     }
     46     node(const ll L,const ll R)//建树
     47     {
     48         l=L,r=R;
     49         if(l==r)//当前节点为叶子结点,无左右子树
     50         {
     51             tag=0;
     52             v=a[l];
     53             ls=rs=NULL;
     54         }
     55         else
     56         {
     57             tag=0;
     58             ll M=(l+r)>>1;
     59             ls=new node(L,M);
     60             rs=new node(M+1,R);
     61             pushup();
     62         }
     63     }
     64     inline bool inrange(const ll L,const ll R)//在查询区间以内
     65     {
     66         return (L<=l)&&(r<=R);
     67     }
     68     inline bool outrange(const ll L,const ll R)//在查询区间以外
     69     {
     70         return (l>R)||(r<L);
     71     }
     72     inline void upd(const ll L,const ll R,const ll w)//区间修改
     73     {
     74         if(inrange(L,R))
     75         {
     76             maketag(w);
     77         }
     78         else if(!outrange(L,R))
     79         {
     80             pushdown();
     81             ls->upd(L,R,w);
     82             rs->upd(L,R,w);
     83             pushup();
     84         }
     85     }
     86     inline ll qry(const ll L,const ll R)//区间查询
     87     {
     88         if(inrange(L,R)) return v;
     89         if(outrange(L,R)) return 0;
     90         pushdown();
     91         return ls->qry(L,R)+rs->qry(L,R);
     92     }
     93 };
     94 
     95 int main(void)
     96 {
     97     scanf("%lld%lld",&n,&m);
     98     for(int i=1;i<=n;i++) scanf("%lld",a+i);
     99     node *rot=new node(1,n);//建树
    100     
    101     for(ll f,x,y,z;m;m--)
    102     {
    103         scanf("%lld",&f);
    104         
    105         if(f==1)
    106         {
    107             scanf("%lld%lld%lld",&x,&y,&z);
    108             rot->upd(x,y,z);//更新操作
    109         }
    110         if(f==2)
    111         {
    112             scanf("%lld%lld",&x,&y);
    113             printf("%lld
    ",rot->qry(x,y));//查询操作
    114         }
    115     }
    116     return 0;
    117 }
  • 相关阅读:
    新加坡
    android alt + /
    豌豆荚开源技术
    有意思的
    android view
    localstorage性能
    Android WebView使用基础
    关于hash
    Android 近百个项目的源代码,覆盖Android开发的每个领域
    10个经典的Android开源项目(附源码包)
  • 原文地址:https://www.cnblogs.com/jd1412/p/13246006.html
Copyright © 2020-2023  润新知