首页 > 其他分享 >线段树模板 洛谷P3374 【模板】树状数组 1

线段树模板 洛谷P3374 【模板】树状数组 1

时间:2023-07-12 19:57:53浏览次数:45  
标签:洛谷 包含 int 线段 tr return P3374 模板

题目传送门

题目描述

如题,已知一个数列,你需要进行下面两种操作:

1.将某一个数加上x

2.求出某区间每一个数的和

输入格式

第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3个整数,表示一个操作,具体如下:

操作1: 格式:1 x k 含义:将第x个数加上k

操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

输出格式

输出包含若干行整数,即为所有操作2的结果。

输入输出样例

输入 #1
5 5
1 5 4 2 3
1 1 3
2 2 5
1 3 -1
1 4 2
2 1 4
输出 #1
14
16

说明/提示

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=10000,M<=10000

对于100%的数据:N<=500000,M<=500000

样例说明:

故输出结果14、16

题解:

嘿嘿,浅浅讲一下思路吧!

首先啊,怎么大的范围,出题人肯定不会让你轻易暴力就能过的,区间求和,修改,我们很容易想到用线段树来解题,浅浅说一下为什么用线段树吧!

首先,线段树,可以有效的节省时间,避免超时的情况出现(好像是废话,哈哈哈哈哈)

其次,线段树可以单点修改,单点查询,区间修改,区间查询,所以正好符合我们这题

那直接上代码!!

AC代码
 #include<iostream>
using namespace std;
const int N = 5 * 1e6 + 10;
int a[N];
struct node {
	int l, r;
	int sum;
}tr[4*N];
void build(int i, int l, int r)//建树
{
	tr[i].l = l;
	tr[i].r = r;
	if (tr[i].l == tr[i].r)//叶子节点
	{
		tr[i].sum = a[tr[i].l];
		return;
	}
	int mid = (l + r) >> 1;
	build(i << 1, l,mid);
	build((i << 1) + 1, mid+1, r);
	tr[i].sum = tr[i << 1].sum + tr[(i << 1) + 1].sum;
}
void add(int i, int l, int k)//l处加k,因为是加单点,所以父节点均可加k,一次结束
{
	if (tr[i].l <= l && tr[i].r >= l)//如果包含该点
	{
		tr[i].sum += k;//加上
		if (tr[i].l == tr[i].r)//叶子节点
			return;
	}
	if(tr[i].l >l|| tr[i].r < l)
		return;
	add((i << 1), l, k);
	add((i << 1) + 1, l, k);
}
int search(int i,int l, int r)
{
	int s = 0;
	if (tr[i].l > r || tr[i].r < l)
		return 0;//不包含的情况
	if (tr[i].l >= l && tr[i].r <= r)
	{
		return tr[i].sum;
	}
	if (tr[i<<1].r >= l)
		s += search((i << 1), l, r);
	if (tr[(i<<1)+1].l <= r)
		s += search((i << 1) + 1, l, r);
	return s;
}
int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i]; 
	build(1, 1, n);//建树
	for (int i = 1; i <= m; i++)
	{
		int x, y, z;
		cin >> x >> y >> z;
			if (x == 1)
			{
				add(1,y, z);
			}
			if (x == 2)
			{
				int ans = 0;
				ans = search(1,y, z);
				cout << ans << endl;
			}
	}
	return 0;

}

标签:洛谷,包含,int,线段,tr,return,P3374,模板
From: https://www.cnblogs.com/haggard/p/17548663.html

相关文章

  • 洛谷 P6892 [ICPC2014 WF] Baggage
    洛谷传送门感觉这题递归的思想挺值得借鉴的。特判\(n=3\)。首先根据样例不难猜测最小次数为\(n\)。事实上最小次数下界为\(n\),因为设\(x\)为当前相邻元素相同对数,不难发现除第一次操作外\(x\)最多增加\(2\),而终态中\(x=2n-2\)。我们尝试构造能达到下界的方案。......
  • 堆(模板)
    题目描述初始小根堆为空,我们需要支持以下3种操作:操作1:1x表示将x插入到堆中操作2:2输出该小根堆内的最小数操作3:3删除该小根堆内的最小数Input第一行包含一个整数N,表示操作的个数接下来N行,每行包含1个或2个正整数,表示三种操作,格式如下:操作1:1x操作2:2操作3:3Outp......
  • 老杜 JavaWeb 讲解(九) ——模板方法设计模式、HttpServlet源码分析
    (十一)模板方法设计模式、HttpServlet源码分析对应视频:20-HttpServlet源码分析及web欢迎页11.1模板方法设计模式不用使用在上面右侧表格中,Person就是模板方法设计模式当中的模板类,通常是抽象类。day()方法就是模板方法设计模式当中的模板方法。模......
  • 「模板」树状数组
    引入题目描述给定\(n\)个数\(a[1],a[2],a[3]...a[n]\),现在又下面两种操作:1.询问区间\([x,y]\)的和,并输出。2.将下标为\(x\)的数增加\(val\)。一共\(x\)此操作\(1\len,m\le100000\),保证在\(int\)范围内。方法一:暴力枚举定义数组\(a\)储存\(n\)个元素。求区间和的时间复......
  • 自用模板
    #pragmaGCCoptimize(2)#include<bits/stdc++.h>#include<iostream>#include<vector>#include<algorithm>#include<set>#include<utility>#include<string.h>#include<ext/rope>#include<queue>#include&l......
  • 业务系统常规部署交接模板
    1总体情况ip应用192.168.1.1前端1192.168.1.2后端1......1.1前端1#1.进程查看#2.服务路径以及启停#3.版本更新#4.日志查看#5.配置文件说明1.2后端1#1.进程查看#2.服务路径以及启停#3.版本更新#4.日志查看......
  • 洛谷 P4869 albus就是要第一个出场 题解
    洛谷P4869albus就是要第一个出场题意给定一个长度为\(n\)的序列\(A\),设可重集合\(S=\left\{\operatorname{xor}_{i=1}^nA_ix_i\midx_i\in\{0,1\}\right\}\),即\(S\)为\(A\)的所有子集的异或和构成的集合。给定一个数\(k\),求\(k\)在\(S\)中的排名。如果\(S\)中......
  • 洛谷 P6109 - [Ynoi2009] rprmq1
    首先将修改操作差分为\(l_1\)时刻给\([l_2,r_2]\)中的值\(+v\),\(r_1+1\)时刻给\([l_2,r_2]\)中的值\(-v\)。这样第\(i\)行的状态相当于执行\(1\simi\)时刻的操作后的状态。猫树分治,把一个询问挂在线段树上满足\(l\lel_1\lemid\ler_1\ler\)的区间\([l,r]\)......
  • 【模板】并查集
    简介并查集是什么并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。并查集其实就是一个树,如果要合并的话就将其中一个的根节点连接到另外一个的根......
  • 洛谷P4715 【深基16.例1】淘汰赛
    写在前面这是本蒟蒻的第三篇题解。由于作者水平不高,本题解存在有数量庞大的错误。对于题解中的错误、可优化部分,欢迎各位大佬批评指正!不合适的部分,还请多多包涵!本题目来源于洛谷。网址https://www.luogu.com.cn/problem/P4715。本博客非营利性,如遇侵权,请联系作者删除,谢谢!题面......