首页 > 其他分享 >线段树

线段树

时间:2022-09-04 20:34:54浏览次数:56  
标签:int 线段 mid len tag sum


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100001;
ll sum[N*4];
ll tag[N*4];
int a[N];
void pushdown(int x, int l_len, int r_len) {
    tag[x*2] += tag[x];
    sum[x*2] += l_len * tag[x];
    tag[x*2+1] += tag[x];
    sum[x*2+1] += r_len * tag[x];
    tag[x] = 0;
}
void build(int x, int l, int r) {
    if (l == r) {
        sum[x] = a[l];
        return;
    }
    int mid = (l + r) / 2;
    build(x*2, l, mid);
    build(x*2+1, mid+1, r);
    sum[x] = sum[x*2] + sum[x*2+1];
}
void add(int x, int l, int r, int L, int R, int val) {
    //x:线段树节点编号
	//[l,r]:当前线段树节点的代表区间
	//[L,R]:要修改的区间
	//val:增加的值
	if (L <= l && r <= R) {//这个线段树区间可以代表一部分修改区间
        tag[x] += val;
        sum[x] += (r - l + 1) * val;
        return;
    }
    int mid = (l + r) / 2;
    if (tag[x]) pushdown(x, mid-l+1, r-mid);
    if (L <= mid) add(x*2, l, mid, L, R, val);//不能代表
    if (mid < R) add(x*2+1, mid+1, r, L, R, val);//到左右儿子继续查找
    sum[x] = sum[x*2] + sum[x*2+1];
}//修改
ll query(int x, int l, int r, int L, int R) {
    if (L <= l && r <= R)
        return sum[x];
    int mid = (l + r) / 2;
    if (tag[x]) pushdown(x, mid-l+1, r-mid);
    ll res = 0ll;
    if (L <= mid) res += query(x*2, l, mid, L, R);
    if (mid < R) res += query(x*2+1, mid+1, r, L, R);
    sum[x] = sum[x*2] + sum[x*2+1];
    return res;
}//查询
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    build(1, 1, n);
    while (m--) {
        int op, x, y, k;
        scanf("%d%d%d", &op, &x, &y);
        if (op == 1) {
            scanf("%d", &k);
            add(1, 1, n, x, y, k);
        } else {
            printf("%lld\n", query(1, 1, n, x, y));
        }
    }
    return 0;
}

标签:int,线段,mid,len,tag,sum
From: https://www.cnblogs.com/hnzzlxs01/p/16655967.html

相关文章

  • CF446C(线段树+斐波那契)
    CF446C(线段树+斐波那契数列)CF链接洛谷链接题目大意:区间加斐波那契数列,区间求和分析:一眼鉴定为线段树难点在于如何打标记,合并和传递标记对于斐波那契数列有几个性......
  • 浅淡线段树合并
    线段树,是信息学比赛中一种强有力的数据结构;动态开点,让线段树在数据范围上挣脱了束缚;线段树合并,让树上问题获得了升华。前言线段树合并的基础——动态开点线段树在初学......
  • 题解 AT5635 Shortest Path on a Line(线段树优化建图)
    题解AT5635ShortestPathonaLineDescription题目传送门题面翻译有一张有\(N\)个点,编号为\(1-N\)的无向图。做\(M\)次操作,每次操作给出三个正整数\(L,R,......
  • [Google] LeetCode 715 Range Module 线段树
    ARangeModuleisamodulethattracksrangesofnumbers.Designadatastructuretotracktherangesrepresentedashalf-openintervalsandqueryaboutthem.......
  • [洛谷P5787] 线段树时间分治
    题目大意给\(n\)个点\(m\)条边,在\(k\)时间内,第\(i\)条边只在\([l_i+1,r_i]\)的时间范围内存在。对于每个\(i\leqk\),输出\(i\)时刻这个图是否是二分图。题......
  • CF633H Fibonacci-ish II 莫队 线段树 矩阵
    CF633HFibonacci-ishII题意很简明同时给人以不可做感。直接暴力大概是\(n^2log\)的优化一下提前排好序从小到大枚举数字再枚举询问可以完成\(n^2\)经过精细的优化......
  • 线段树
    线段树真是太强啦!用途线段树不同与树状数组,他支持单点查询,单点修改,区间修改,区间查询,需要\(4\)个函数进行,分别为\(build,updata,query,lazy\)组成,即搭建,更新......
  • 模拟赛 d (扫描线,三维偏序,线段树合并,并查集,线段树上二分)
    PRO题目大意:给定$N$个矩形,求连通块个数。($1\leqN,x_1,x_2,y-1,y_2\leq100000$)SOL乍一看就能知道是扫描线,不过这题的细节恐怖的要命。(std同样看不懂,自己魔改了一......
  • 线段树 C++实现 树形式
    网上看了一圈,看到几个都是用数组实现的我用树结构重写了一遍#ifndefSEGMENTTREE_H#defineSEGMENTTREE_H#include<vector>template<typenameT>classSegmentTree......
  • 线段树的分裂和合并(加强版)
    上一篇文章讲了线段树分裂和合并的模板题,下面加强一下理解题目链接:https://www.luogu.com.cn/problem/P4556深绘里一直很讨厌雨天。灼热的天气穿透了前半个夏天,后来一......