线段树二(区间修改)

概述

区间修改即将一个区间内所有值改为一个值(或加上一个值),为了执行快速,我们通常用“懒”标记维护整个区间值的情况,在需要是再将这个“懒”标记传到该节点的两个子节点上。

模版(此为在整个区间上加上一个值)(洛谷p3372

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const long long inf=2e18+7;
long long d[1000000],n,color[1000000];

//查找
long long visit(long long le,long long ri,long long k,long long x,long long y)
{     if(le>=x&&ri<=y){
        return d[k];
      }
      long long mid=(le+ri)>>1,ans=0;
      if(color[k]){
          d[k*2]+=(mid-le+1)*color[k];
          d[k*2+1]+=(ri-mid)*color[k];
          color[k*2]+=color[k];
          color[k*2+1]+=color[k];
          color[k]=0;
      }
      if(mid>=x)ans+=visit(le,mid,k*2,x,y);
      if(mid<y)ans+=visit(mid+1,ri,k*2+1,x,y);
      d[k]=d[k*2]+d[k*2+1];
      return ans;
}

//更改
void go(long long le,long long ri,long long k,long long x,long long y,long long wh)
{     if(le>=x&&ri<=y){
        d[wh]+=(ri-le+1)*k;
        color[wh]+=k;
        return;
      }
      long long mid=(le+ri)>>1;
      if(color[wh]){
          d[wh*2]+=(mid-le+1)*color[wh];
          d[wh*2+1]+=(ri-mid)*color[wh];
          color[wh*2]+=color[wh];
          color[wh*2+1]+=color[wh];
          color[wh]=0;
      }
      if(mid>=x)
        go(le,mid,k,x,y,wh*2);
      if(mid<y)
        go(mid+1,ri,k,x,y,wh*2+1);
      d[wh]=d[wh*2]+d[wh*2+1];
}
int main()
{     long long m,i,j;
      scanf("%lld%lld",&n,&m);
      for(i=1;i<=n;i++){
          long long x;
          scanf("%lld",&x);
          go(1,n,x,i,i,1);
      }
      for(i=1;i<=m;i++){
          long long x,y,k;
          long long wh;
          scanf("%lld",&wh);
          if(wh==1){
          scanf("%lld%lld%lld",&x,&y,&k);
             go(1,n,k,x,y,1);
        }
        else {
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",visit(1,n,1,x,y));
        }
      }
      return 0;
}
注意:在查找和更改时都要下穿“懒”标记

时间: 2024-10-05 08:25:55

线段树二(区间修改)的相关文章

hihoCode 1078 : 线段树的区间修改

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

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

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

线段树的区间修改

线段树的区间修改 时间限制: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

模板 线段树的区间修改

线段树的区间修改 区间绝对标记 改成同一个数 注意打标记前 要先判断 是否有标记 这道题不能像加法标记一样 标记初始化为 0 如果这道题 可以将数变成 0 那么0 就不能为初始值了 然后我们初始值要选择一个不会被干扰到的数字 比如 -1 就不会变成 -1 另外还要注意在标记清空时 要将标记 变成 -1 而不是 0 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstr

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]