【模板】线段树 区间修改+区间查询

题目大意:维护一个长度为 N 的序列,支持区间修改、区间查询两种操作。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;

inline int read(){
    int x=0,f=1;char ch;
    do{ch=getchar();if(ch==‘-‘)f=-1;}while(!isdigit(ch));
    do{x=x*10+ch-‘0‘;ch=getchar();}while(isdigit(ch));
    return f*x;
}

int n,q,a[maxn];
struct node{int lc,rc;long long sum,tag;};
struct Segment_Tree{
    #define ls t[k].lc
    #define rs t[k].rc
    node t[maxn<<1];
    int tot;
    Segment_Tree():tot(1){}
    inline void pushup(int k){
        t[k].sum=t[ls].sum+t[rs].sum;
    }
    inline void pushdown(int k,int l,int r){
        int mid=l+r>>1;
        t[ls].sum+=t[k].tag*(mid-l+1),t[ls].tag+=t[k].tag;
        t[rs].sum+=t[k].tag*(r-mid),t[rs].tag+=t[k].tag;
        t[k].tag=0;
    }
    void build(int k,int l,int r){
        if(l==r){t[k].sum=a[l];return;}
        int mid=l+r>>1;
        ls=++tot,build(ls,l,mid);
        rs=++tot,build(rs,mid+1,r);
        pushup(k);
    }
    void modify(int k,int l,int r,int x,int y,int val){
        if(l==x&&y==r){t[k].sum+=(r-l+1)*(long long)val,t[k].tag+=val;return;}//一定不要忘记开long long
        int mid=l+r>>1;
        pushdown(k,l,r);
        if(y<=mid)modify(ls,l,mid,x,y,val);
        else if(x>mid)modify(rs,mid+1,r,x,y,val);
        else modify(ls,l,mid,x,mid,val),modify(rs,mid+1,r,mid+1,y,val);
        pushup(k);
    }
    long long query(int k,int l,int r,int x,int y){
        if(l==x&&r==y)return t[k].sum;
        int mid=l+r>>1;
        pushdown(k,l,r);
        if(y<=mid)return query(ls,l,mid,x,y);
        else if(x>mid)return query(rs,mid+1,r,x,y);
        else return query(ls,l,mid,x,mid)+query(rs,mid+1,r,mid+1,y);
    }
}sgt;

void read_and_parse(){
    n=read(),q=read();
    for(int i=1;i<=n;i++)a[i]=read();
    sgt.build(1,1,n);
}

void solve(){
    int opt,l,r,val;
    while(q--){
        opt=read(),l=read(),r=read();
        if(opt==1)val=read(),sgt.modify(1,1,n,l,r,val);
        else printf("%lld\n",sgt.query(1,1,n,l,r));
    }
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

原文地址:https://www.cnblogs.com/wzj-xhjbk/p/9976731.html

时间: 2024-08-29 04:23:38

【模板】线段树 区间修改+区间查询的相关文章

hdu1698 Just a Hook(线段树+区间修改+区间查询+模板)

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 54923    Accepted Submission(s): 25566 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of

SPOJ GSS2 - Can you answer these queries II(线段树 区间修改+区间查询)(后缀和)

GSS2 - Can you answer these queries II #tree Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse to write two program of same kind at all. So he always failes in contests. When

hihocoder1080线段树+区间修改+区间查询+多个懒标记

题目链接:http://hihocoder.com/problemset/problem/1080 对于这种不止一个懒标记的线段树,只要弄清楚各种操作和各种懒标记间的关系就OK了. 我的代码: 1 #include <cstdio> 2 3 using namespace std; 4 5 #define MAXN 100005 6 7 int p[MAXN]; 8 9 struct segNode 10 { 11 int left, right, sum, dd, vv; 12 bool l

算法模板——线段树区间修改区间求和

该模板实现的功能——进行区间的乘法和加法,以及区间的求和(1:乘法 2:加法 3:求和)详见BZOJ1798 1 type 2 vet=record 3 a0,a1:int64; 4 end; 5 var 6 i,j,k,l,m,n,a2,a3,a4:longint; 7 p:int64; 8 d1,d2,d:vet; 9 a,c:array[0..1000000] of int64; 10 b:array[0..1000000] of vet; 11 function min(x,y:long

A Simple Problem with Integers POJ - 3468 线段树区间修改+区间查询

//add,懒标记,给以当前节点为根的子树中的每一个点加上add(不包含根节点) // #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int N = 100010; int n, m; int w[N]; struct Node { int l, r;

线段树区间修改模板

本来打算把大白书第三章一口气攻下来的,但是这个线段树也是卡了好久. 不敢过题太快,怕自己走马观花到头来结果什么都不会. 可也不能再拖了,在做题中也许有更多的体会. 模板一:1 L R v 表示区间[L, R]所有元素都加上v2 L R   表示查询区间[L, R]的sum, min, maxsumv[o]的定义为:如果只执行节点o及其子孙节点的中的add操作,节点o对应区间中所有数之和 1 //线段树区间修改 2 //1 L R v 表示区间[L, R]所有元素都加上v 3 //2 L R 表示

【模板】线段树区间修改

区间修改: 区间修改过程类似于区间询问,例如将[ul, ur]内的所有元素都加上v,则进行如下操作: 当当前区间被区间[ul, ur]所包含时, 当前的节点值加上区间长度(r - l  + 1)乘以v 对当前节点的lazy-tag加上v,修改结束 否则,将当前节点的lazy-tag下传,分别修改左孩子和右孩子(一定条件下),然后更新此节点的值 lazy-tag下传: 如果当前节点没有lazy-tag,直接return 否则:1. 将左孩子右孩子分别加上lazy-tag * 区间长度的值  2.

线段树区间修改 P3372 【模板】线段树 1

题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和 输出格式: 输出包含若干行整

poj 2777 Count Color(线段树区间修改)

题目链接:http://poj.org/problem?id=2777 题目意思:就是问你在询问的区间里有几种不同的颜色 思路:这题和一般的区间修改差不多,但是唯一不同的就是我们要怎么计算有种颜色,所以这时候我们就需要把延时标记赋予不同的意义,当某段区间有多种颜色时就赋值为-1,当为一种颜色时就把它赋值为这个颜色的号数.这儿我们要怎么统计询问区间不同的颜色数叻,为了不重复计算同一种颜色,那么我们就需要用一个数组来标记计算过的颜色,当我们下次遇到时就不需要再次计算了.... 代码核心处就在计数那儿