模板 线段树的区间修改

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

注意打标记前 要先判断 是否有标记
这道题不能像加法标记一样 标记初始化为 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 }
时间: 2024-10-14 04:00:14

模板 线段树的区间修改的相关文章

hiho一下20周 线段树的区间修改

线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段区间[L, R]

hihoCode 1078 : 线段树的区间修改

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

线段树的区间修改

线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段区间[L, R]

hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   Accepted: 17753 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

POJ 2828 Buy Tickets (线段树,区间修改)

逆向思维.从最后一位开始考虑,用线段树查询空位置. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include &l

培训补坑(day7:线段树的区间修改与运用)(day6是测试,测试题解以后补坑QAQ)

补坑咯~ 今天围绕的是一个神奇的数据结构:线段树.(感觉叫做区间树也挺科学的.) 线段树,顾名思义就是用来查找一段区间内的最大值,最小值,区间和等等元素. 那么这个线段树有什么优势呢? 比如我们要多次查询1-n中的最大值,那么我们如果使用暴力来查找,那么我们每次查找的复杂度就是O(n) 但是如果我们把一个个区间变成树上的一个个点,并且我们严格保证树的深度,那么我们每次查找的复杂度就是O(logn) 这样就能让查询变得更快. 我们先简单讲一下线段树的存储(图中的标号就是线段树数组标号) 这就是线段

HZAU 1207 Candies(线段树区间查询 区间修改)

[题目链接]http://acm.hzau.edu.cn/problem.php?id=1207 [题意]给你一个字符串,然后两种操作:1,将区间L,R更新为A或者B,2,询问区间L,R最长的连续的B为多长. [分析]典型线段树,每个节点维护该区间左边连续B的长度,右边连续B的长度,最长的连续B的长度,还有lazy标记. #include <cstdio> #include <cstring> #include <iostream> #include <algor

hdu 5381 The sum of gcd(线段树等差数列区间修改+单点查询)

题意: 给出一个数组a,叫你每次询问如下等式的值. f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj) 解析: 思考了很久终于理解了学长的思路 给你一个序列,这个序列的子序列gcd的个数不会超过logN个(N为每个数字,最大能取到的范围) 因为求gcd是递减的,每次至少除以2,所以gcd的个数只会有logN个. 然后让我们来看看题目要求的是什么. 所有子区间的gcd的和. 比如[1, 5]这个区间可以分解成如下子区间. [1, 1] [1, 2] [1, 3] [1, 4]