模板 线段树的区间修改

Posted third2333

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板 线段树的区间修改相关的知识,希望对你有一定的参考价值。

线段树的区间修改 
区间绝对标记 改成同一个数

注意打标记前 要先判断 是否有标记
这道题不能像加法标记一样 标记初始化为 0
如果这道题 可以将数变成 0 那么0 就不能为初始值了
然后我们初始值要选择一个不会被干扰到的数字
比如 -1 就不会变成 -1

另外还要注意在标记清空时 要将标记 变成 -1 而不是 0

 

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <iostream>
  8 #include <iomanip>
  9 #define ll long long 
 10 using namespace std ; 
 11 
 12 const int maxn = 1e5+11 ; 
 13 struct node{
 14     int l,r ; 
 15     ll sum,mark ; 
 16 }tree[maxn*4];
 17 int n,Q,type,L,R,v ; 
 18 int a[maxn] ; 
 19 ll ans ; 
 20 
 21 inline int read() 
 22 {
 23     char ch = getchar() ; 
 24     int x = 0 , f = 1 ; 
 25     while(ch<0||ch>9) { if(ch==-) f = -1 ; ch = getchar() ; } 
 26     while(ch>=0&&ch<=9) { x = x*10+ch-48 ; ch = getchar() ; } 
 27     return x * f ; 
 28 }
 29 
 30 inline void pushup(int root) 
 31 {
 32     tree[root].sum = tree[root*2].sum + tree[root*2+1].sum ;     
 33 }
 34 
 35 inline void build(int l,int r,int root) 
 36 {
 37     tree[root].l = l ;  tree[root].r = r ; 
 38     tree[root].mark = -1 ; 
 39     if(l==r) 
 40     {
 41         tree[root].sum = a[ l ] ; tree[root].mark = 0 ; 
 42         return ; 
 43     }
 44     int mid = (l + r) >>1 ; 
 45     build(l,mid,root*2) ; 
 46     build(mid+1,r,root*2+1) ; 
 47     pushup(root) ;  
 48 }
 49 
 50 inline void pushdown(int root) 
 51 {
 52     if(tree[root].mark == -1) return ; 
 53     tree[root*2].mark = tree[root].mark ; 
 54     tree[root*2].sum = ( 1ll*tree[root*2].r - tree[root*2].l+1) * tree[root].mark ; 
 55     tree[root*2+1].mark = tree[root].mark ; 
 56     tree[root*2+1].sum = ( 1ll*tree[root*2+1].r - tree[root*2+1].l+1) * tree[root].mark ;  
 57     tree[root].mark = -1 ;     //
 58 }
 59 
 60 inline void updata(int l,int r,int v,int root) 
 61 {
 62     if(l==tree[root].l&&r==tree[root].r) 
 63     {
 64         tree[root].sum = (1ll*tree[root].r-tree[root].l+1) * v ; 
 65         tree[root].mark = v ; 
 66         return ; 
 67     }
 68     pushdown(root) ; 
 69     int mid = (tree[root].l + tree[root].r) >>1 ; 
 70     if( r<=mid ) updata(l,r,v,root*2) ; 
 71     else 
 72     if( l > mid) updata(l,r,v,root*2+1) ; 
 73     else
 74     {
 75         updata(l,mid,v,root*2) ; 
 76         updata(mid+1,r,v,root*2+1) ; 
 77     }
 78     pushup(root) ; 
 79 }
 80 
 81 inline ll query(int l,int r,int root) 
 82 {
 83     if(tree[root].l==l&&tree[root].r==r) 
 84         return tree[root].sum ; 
 85     pushdown(root) ;               //
 86     int mid = (tree[root].l + tree[root].r ) >>1;  
 87     if( r<=mid ) return query(l,r,root*2) ; 
 88     if( l > mid ) return  query(l,r,root*2+1) ; 
 89     ll ans = 0 ; 
 90     ans+=query(l,mid,root*2) ; 
 91     ans+=query(mid+1,r,root*2+1) ; 
 92     return ans ; 
 93 }
 94 
 95 int main() 
 96 {
 97     n = read() ;  
 98     for(int i=1;i<=n;i++) a[ i ] = read() ;  
 99     Q = read() ;   
100     build(1,n,1) ; 
101     
102     for(int i=1;i<=Q;i++) 
103     {
104         type = read() ; L = read() ; R = read() ; 
105         if(type==1) 
106         {
107             v = read() ; 
108             updata(L,R,v,1) ; 
109         }
110         else
111         {
112             ans = query(L,R,1) ; 
113             printf("%lld\n",ans) ; 
114         }
115     }
116     return 0 ; 
117 }

 


以上是关于模板 线段树的区间修改的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P3372 模板线段树 1

HDU 1166 - 敌兵布阵 - [单点修改区间查询zkw线段树]

如何利用树状数组修改一个区间?

P3372 模板线段树 1

P3372 模板线段树 1

线段树的思路