首页 > 其他分享 >线段树

线段树

时间:2023-08-24 16:56:36浏览次数:34  
标签:rs int 线段 tr lt include

线段树 vs 树状数组

  1. 代码长度: 树状数组段
  2. 可扩展性:线段树强, 二树状数组仅局限于和的处理
  3. 思维难度:线段树简单 比如 区查区改 树状数组还要打开多项式搞

延迟标记:为了处理当修改区间是\([1,n]\)时所有节点都要被修改一遍的情况

如果修改区间覆盖当前区间,那么这颗子树之内所有节点都要修改,干脆在根打个标记,延迟更新
等到出现 1.修改区间未覆盖当前区间(不能省) 2.需要查询 两种情况时 下传标记

区查区改

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std ;

typedef long long ll ;
const int N = 100010 ;

int n, q ;
int a[N] ;

struct node {
	int l, r ; ll v ;
	int lt ; // lazy tag 
	#define ls(x) tr[x].l
	#define rs(x) tr[x].r
	#define v(x) tr[x].v
	#define lt(x) tr[x].lt
} tr[N * 4] ;

void build(int x, int l, int r) {
	ls(x) = l, rs(x) = r ; lt(x) = 0 ;
	if (l == r) {
		v(x) = a[l] ;
		return ;
	}
	int mid = (l + r) >> 1 ;
	build(x * 2, l, mid) ;
	build(x * 2 + 1, mid + 1, r) ;
	v(x) = v(x * 2) + v(x * 2 + 1) ;
} 

int spread(int x) {
	if (lt(x) != 0) {
		lt(x * 2) += lt(x) ;
		lt(x * 2 + 1) += lt(x) ;
		v(x * 2) += lt(x) * (rs(x * 2) - ls(x * 2) + 1) ;
		v(x * 2 + 1) += lt(x) * (rs(x * 2 + 1) - ls(x * 2 + 1) + 1) ;
		lt(x) = 0 ;
	}
}

void modify(int x, int l, int r, int c) {
	if (l <= ls(x) && rs(x) <= r) {
		v(x) += c * (rs(x) - ls(x) + 1) ;
		lt(x) += c ;
		return ;
	}
	spread(x) ;
	int mid = (ls(x) + rs(x)) >> 1 ;
	if (l <= mid) modify(x * 2, l, r, c) ;
	if (mid + 1 <= r) modify(x * 2 + 1, l, r, c) ;
	v(x) = v(x * 2) + v(x * 2 + 1) ;
}

ll query(int x, int l, int r) {
	spread(x) ;
	if (l <= ls(x) && rs(x) <= r) return v(x) ;
	ll ans = 0 ; int mid = (ls(x) + rs(x)) >> 1 ;
	if (l <= mid) ans += query(x * 2, l, r) ;
	if (mid + 1 <= r) ans += query(x * 2 + 1, l, r) ;
	return ans ;
} 

char get() {
	char t = getchar() ;
	while (!isalpha(t)) t = getchar() ;
	return t ;
}

int main() {
	scanf("%d%d", &n, &q) ;
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]) ;
	build(1, 1, n) ;
	while (q--) {
		char op = get() ; 
		if (op == 'C') {
			int l, r, c ; scanf("%d%d%d", &l, &r, &c) ;
			modify(1, l, r, c) ;
		} else {
			int l, r ; scanf("%d%d", &l, &r) ;
			printf("%lld\n", query(1, l, r)) ;
		}
	}
}

标签:rs,int,线段,tr,lt,include
From: https://www.cnblogs.com/lighthqg/p/17654565.html

相关文章

  • 【230823-3】▲ABC中,∠ABC=90°,AB=4,BC=3,点D在线段AC上,若角BDC=45°,则BD=?,Cos∠ABD=?
    ......
  • 数学——点到线段的最短距离
    点到线段最短距离的运算与点到直线的最短距离的运算二者之间存在一定的差别,即求点到线段最短距离时需要考虑参考点在沿线段方向的投影点是否在线段上,若在线段上才可采用点到直线距离公式。通俗的说,我们按照求点到直线的距离作垂线后,交点不一定在线段上。如图\(1\)所示。通常......
  • [Trick] [算法学习笔记] 线段树
    事先声明:本文并非线段树教学。只是一些理解Trick。若您需从0学起线段树建议您移步其他博文呢qwq感谢Idea提供尺子姐姐的博客!,尺子好闪,拜谢尺子!我们在学习线段树的时候,对于乘法“lazytag先乘再加”是不是难以理解?这里介绍一种线段树思考方法。我们可以将序列中的每个元素......
  • 线段树进阶
    多信息合并\(\text{GSS3Solution}\)\(\text{link}\)对于线段树的每个结点,记录其区间和(\(sum\)),区间前后缀最大子段和(\(lmax,rmax\))和区间最大子段和(\(vmax\))。合并:\[vmax=\max\{vmax_{lson},vmax_{rson},rmax_{lson}+lmax_{rson}\}\]\[lmax=\max\{lmax_{lson},sum_{lson}+lm......
  • 【学习笔记】优化建图相关(线段树优化,倍增优化)
    优化建图发现并没有人写得很详细的样子,那我也摆烂好惹点击查看目录目录前言线段树优化建图单点连区间区间连区间例题解题:倍增优化建图例题解题:前言众所周知,连边的时间复杂度一般是\(O(1)\),但,当连边的对象是一个连续的树上区间的时候,我们或许有更优的连边方式:优化建图。......
  • 大抄线段树历史值问题
    历史值问题历史值:在维护序列\(A\)的同时,在每次操作后,序列\(A\)会对序列\(B\)的对应位置产生贡献。历史版本和:每次操作后,\(B_i\leftarrowB_i+A_i\)。历史最大值:每次操作后,\(B_i=\max(B_i,A_i)\)。历史版本和:给定操作:①区间加。②查询区间和。③查询区间......
  • 【230820-1】▲ABC中,AC=根号二,BC=根号六,S△ABC=根号三/2,若线段BA上的延长线存在点D,使
    ......
  • 线段树与树状数组
    $$\texttt{线段树}$$OI-wikiLink线段树是一种用于维护区间信息的数据结构,可以在\(O(\logn)\)的复杂度下求出一个大小为\(n\)的数组的区间信息(如区间和、区间最大值等),也可以在同样时间复杂度下实现单点修改和区间修改等操作。基本结构:......
  • checkmin 线段树
    题意:给你一个长为\(n\)的序列\(a\),支持:1lrx:\(\foralla_i\in[l,r],a_i\gets\min(a_i,x)\)。2lr:求\(\sum_{i\in[l,r]}a_i\)。3lr:求\(\max_{i\in[l,r]}a_i\)。数据范围:\(n,m\le10^5\)。思路:考虑线段树,显然一个结点需要维护的基本信息为\(sum\)和......
  • dfs序线段树
    dfs序线段树1.树上操作思路遍历一整棵树,记录一下节点\(u\)的所对应的子树的节点数\(siz_u\)以及\(dfs\)序\(dfn_u\)根据整棵树的\(dfs\)序,我们可以把树变成了一个序列再维护线段树,\(\text{update(l,r,x)}\)表示将\([\text{l,r}]\)上值加上\(x\).\(\text{query(......