首页 > 其他分享 >线段树

线段树

时间:2024-07-23 21:54:35浏览次数:10  
标签:lazy int sum tr mid id 线段

自己看:https://blog.csdn.net/weq2011/article/details/128791426

看懂就没问题了

 

 

单点修改+区间查询


 

https://www.luogu.com.cn/problem/P3374

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+5;

int n, m, x, y, op, w[N], k, tr[4*N];
void build(int id, int L, int R)
{
	if (L==R)
	{
		tr[id]=w[L];
		return ;
	}
	
	int mid=(L+R)>>1;
	build(id*2, L, mid);
	build(id*2+1, mid+1, R);
	
	tr[id]=tr[id*2]+tr[id*2+1];
}
void change(int id, int L, int R, int x, int v)
{
	if (L==R)
	{
		tr[id]+=v;
		return ;
	}
	
	int mid=(L+R)>>1;
	if (x<=mid) change(id*2, L, mid, x, v);
	else change(id*2+1, mid+1, R, x, v);
	
	tr[id]=tr[id*2]+tr[id*2+1];
}
int find(int id, int L, int R, int x, int y)
{
	if (x<=L && R<=y) return tr[id];
	
	int mid=(L+R)>>1, res=0;
	if (x<=mid) res+=find(id*2, L, mid, x, y);
	if (y>=mid+1) res+=find(id*2+1, mid+1, R, x, y);
	
	return res;
}
signed main()
{
	scanf("%lld%lld", &n, &m);
	for (int i=1; i<=n; i++) scanf("%lld", &w[i]);
	build(1, 1, n);
	
	for (int i=1; i<=m; i++)
	{
		scanf("%lld", &op);
		if (op==1)
		{
			scanf("%lld%lld", &x, &k);
			change(1, 1, n, x, k);
		}
		else if (op==2)
		{
			scanf("%lld%lld", &x, &y);
			printf("%lld\n", find(1, 1, n, x, y));
		}
	}
	return 0;
}

  

 

 

 

区间修改+区间查询


 

https://www.luogu.com.cn/problem/P3372

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;

struct node
{
	int lazy, sum;
}tr[4*N];
int n, m, x, y, op, w[N], k;
void build(int id, int L, int R)
{
	if (L==R)
	{
		tr[id].sum=w[L];
		return ;
	}
	
	int mid=(L+R)>>1;
	build(id*2, L, mid);
	build(id*2+1, mid+1, R);
	
	tr[id].sum=tr[id*2].sum+tr[id*2+1].sum;
}
void push_down(int id, int L, int R)
{
	if (tr[id].lazy!=0)
	{
		int mid=(L+R)>>1;
		tr[id*2].lazy+=tr[id].lazy;
		tr[id*2+1].lazy+=tr[id].lazy;
		tr[id*2].sum+=tr[id].lazy*(mid-L+1);
		tr[id*2+1].sum+=tr[id].lazy*(R-(mid+1)+1);
		tr[id].lazy=0;
	}
}
void push_up(int id)
{
	tr[id].sum=tr[id*2].sum+tr[id*2+1].sum;
}
void change(int id, int L, int R, int x, int y, int v)
{
	if (x<=L && R<=y)
	{
		tr[id].lazy+=v;
		tr[id].sum+=v*(R-L+1);
		return ;
	}
	push_down(id, L, R);
	
	int mid=(L+R)>>1;
	if (x<=mid) change(id*2, L, mid, x, y, v);
	if (y>=mid+1) change(id*2+1, mid+1, R, x, y, v);
	
	push_up(id);
}
int find(int id, int L, int R, int x, int y)
{
	if (x<=L && R<=y) return tr[id].sum;
	push_down(id, L, R);
	
	int mid=(L+R)>>1;
	int res=0;
	
	if (x<=mid) res+=find(id*2, L, mid, x, y);
	if (y>=mid+1) res+=find(id*2+1, mid+1, R, x, y);
	
	return res;
}
signed main()
{
	scanf("%lld%lld", &n, &m);
	for (int i=1; i<=n; i++) scanf("%lld", &w[i]);
	build(1, 1, n);
	
	for (int i=1; i<=m; i++)
	{
		scanf("%lld", &op);
		if (op==1)
		{
			scanf("%lld%lld%lld", &x, &y, &k);
			change(1, 1, n, x, y, k);
		}
		else if (op==2)
		{
			scanf("%lld%lld", &x, &y);
			printf("%lld\n", find(1, 1, n, x, y));
		}
	}
	return 0;
}

  

 

标签:lazy,int,sum,tr,mid,id,线段
From: https://www.cnblogs.com/didiao233/p/18319717

相关文章

  • [Vani有约会] 雨天的尾巴 /【模板】线段树合并
    [Vani有约会]雨天的尾巴/【模板】线段树合并题目背景深绘里一直很讨厌雨天。灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。无......
  • 线段树优化建图一种编号方式的理解
    intid(intl,intr){return(l+r)|(l!=r);}//代码1证明思路:引导并说明某种做法发生冲突的情况,并证明修改后不会发生冲突首先让我们考虑如果为intid(intl,intr){return(l+r);}//代码2会出现什么冲突,如图此时[1,3]与[2,2],[1,5]与[3,3]冲突结论1:线段树中序......
  • 数据结构——李超线段树 学习笔记
    数据结构——李超线段树学习笔记维护直线考虑线段树维护区间最优线段。其中,最优线段指的是,在区间\([l,r]\)中,中点\(mid\)处最优的线段。我们称一个线段在单点更优/最优,显然,是指此处的函数值更大。我们下面称一个线段在区间内更优/最优,是指在中点处的比较。......
  • 线段树分治
    线段树分治线段树分治可以解决这样的问题:对于一些操作,每个操作只在\(l\)~\(r\)的的时间内有效。对于一些操作,询问某个时间点所有操作的贡献。经典例题算法思路对于这道题,因为二分图的充要条件是不存在奇环,所以可以使用扩展域并查集解决。我们考虑离线优化:对于每......
  • 线段树优化建图
    $\quad$在做题时,我们会遇到这种问题:区间性的连边。$\quad$显然,直接连边很容易\(T\)掉,而且内存占用也是我们无法接受的,所以我们就可以采用一种更加方便(其实看起来更麻烦)的方法--线段树优化建图。$\quad$首先我们要有一棵入树与出树(这里用一下_ducati的图)$\quad$入树......
  • 线段树优化建图
    首先看这个问题:一张\(N\)个点的有向图,初始没有任何边,有\(M\)次操作:建\(1\)条边\(u\rightarrowv\),边权为\(w\)。建\(r-l+1\)条边\(u\rightarrow\foralli\in[l,r]\),边权为\(w\)。建\(r-l+1\)条边\(\foralli\in[l,r]\rightarrowu\),边权为\(w\)。求建完边......
  • 【学习笔记】线段树优化建图
    前言2023.5.31贺了线段树优化建图板子。当时那段时间还被\(bobo\)一顿乱\(D\),让我多写点\(DP\),数学,少些点重复的数据结构。2024.7.19没想到暑假集训CSP提高模拟2\(T3\)放了个线段树优化建图板子,加上之前线段树优化建图代码是贺的,今年寒假本想找时间步一下的结果没去......
  • 线段树
    把给定的区间转换成如图所示的一棵二叉树每次把区间一分为2,左边是左儿子,右边是右儿子对于每个节点的信息,都可以由两个儿子的信息得到如何单点查询/修改可以发现,两个儿子处理的区间没有交集,所以每次只要判断是在左儿子还是在右儿子,不断的递归对于区间查询,每一......
  • 线段树(原理、构造和区间查询,例题:Balanced Lineup)
    概念原理    线段树是分治法和二叉树的结合,二叉树上的节点都是根据分治得到的。节点所表示的,也就是线段,可以是区间和、最值或者是其他的,,每次分治,左右子树各一半,每个节点的值代表了以它为根的子树上所有节点的值。通过线段树,大区间的解可以从小区间的解合并而来。构......
  • 线段树优化建图
    为什么?什么时候用线段树优化建图例题如果此时暴力建边\(O(n^{2})\)肯定会TLE观察到题目中的“区间”此时考虑用线段树优化建图,在每个区间上连边(线段树上只有\(\log{n}\)个区间)来减少边的个数实现方法?摘抄自tzx_wk我们就拿\(2\)操作来举例吧。现在假设假如有一个点......