首页 > 其他分享 >树状数组和线段树板子

树状数组和线段树板子

时间:2024-07-02 21:55:49浏览次数:1  
标签:pr 树状 int 线段 mid 板子 include ll pl

树状数组板子

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
#define IOS ios::sync_with_stdio(false), cin.tie(0) ,cout.tie(0)
using namespace std;
typedef unsigned long long ll;

const int N = 1e3 + 10;
int tree[N];
#define lowbit(x) ((x)&(-x))
void update(int x, int d)
{
	//单点修改:修改元素a[x],使得a[x] += d
	while (x < N)
	{
		tree[x] += d;
		x += lowbit(x);
	}
}
int sum(int x)//查询前缀和,返回前缀和sum=a[1] + a[2] + ... + a[x]
{
	int ans = 0;
	while (x > 0)
	{
		ans += tree[x];
		x -= lowbit(x);
	}
	return ans;
}

核心应用点在于单点修改+ 区间查询,然后改成差分数组可以变成区间修改和单点查询
线段树板子:

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
#define IOS ios::sync_with_stdio(false), cin.tie(0) ,cout.tie(0)
using namespace std;
typedef long long ll;
const int N = 1e5+10;
ll a[N];
ll tree[N << 2];//tree[i]是第i个节点的值,表示一个线段区间的‘代表值’,比如区间和、最值
ll tag[N << 2];//tag[i]是第i个节点的lazy-tag,统一记录这个区间的修改
ll ls(ll p) { return p << 1;}
ll rs(ll p) { return p << 1 | 1; }
//push_up可变
void push_up(ll p)
{
	tree[p] = tree[ls(p)] + tree[rs(p)];
	//push_up的功能就是从下到上传递区间值,用于建树
}
void build(ll p, ll pl, ll pr)//建树:p为节点编号,指向区间[pl,pr]
{
	tag[p] = 0;
	if (pl == pr) { tree[p] = a[pl]; return; }//叶子节点
	ll mid = (pl + pr) >> 1;
	build(ls(p), pl, mid);
	build(rs(p), mid + 1, pr);
	push_up(p);
}
//addtag可变
void addtag(ll p, ll pl, ll pr, ll d)
{
	tag[p] += d;
	tree[p] += d * (pr - pl + 1);
}
void push_down(ll p, ll pl, ll pr)
{
	if (tag[p])
	{
		ll mid = (pl + pr) >> 1;
		addtag(ls(p), pl, mid, tag[p]);
		addtag(rs(p), mid + 1, pr, tag[p]);
		tag[p] = 0;
	}
}
//update的根据题目来,可变
void update(ll L, ll R, ll p, ll pl, ll pr, ll d)//区间修改:[L,R]内每个元素+d
{
	if (L <= pl and pr <= R)
	{
		addtag(p, pl, pr, d);
		return;
	}
	push_down(p, pl, pr);
	ll mid = (pl + pr) >> 1;
	if (L <= mid)update(L, R, ls(p), pl, mid, d);//递归左子树
	if (R > mid)update(L, R, rs(p), mid + 1, pr, d);
	push_up(p);
}
ll query(ll L, ll R, ll p, ll pl, ll pr)
{
	//查询区间[L,R],p是当前节点的编号,[pl,pr]是节点p表示的线段区间
	if (pl >= L and pr <= R) { return tree[p]; }
	push_down(p, pl, pr);
	ll res = 0;
	ll mid = (pl + pr) >> 1;
	if (L <= mid)res += query(L, R, ls(p), pl, mid);
	if (R > mid)res += query(L, R, rs(p), mid + 1, pr);
	return res;
}
int main()
{
	ll n, m; cin >> n >> m;//n:数字个数,m:操作次数
	for (ll i = 1; i <= n; i++)cin >> a[i];
	build(1, 1, n);//※
	while (m--)
	{
		ll q, L, R, d; cin >> q;
		if (q == 1)
		{
			cin >> L >> R >> d;
			update(L, R, 1, 1, n, d);

		}
		else 
		{
			cin >> L >> R;
			cout << query(L, R, 1, 1, n);
		}
	}
	return 0;
}

标签:pr,树状,int,线段,mid,板子,include,ll,pl
From: https://www.cnblogs.com/zzzsacmblog/p/18280585

相关文章

  • 线段树基础设计的个人理解
    概述线段树是一棵二叉搜索树,每个树节点代表一个线段或者说一个区间范围,常用于解决各种区间修改、区间查询问题,本文暂时只讲述基础概念,用经典的区间最值问题作为示例。数据结构经典代码模板都是用数组来实现线段树,按照层序遍历的顺序给每个节点分配数组空间,从根节点代表的......
  • (线段树,最小值不能低于0的)北京建筑大学2024年程序设计竞赛 A 寿命修改
    题意:code:#pragmaGCCoptimize("O3")#pragmaGCCoptimize("Ofast")#pragmaGCCoptimize("unroll-loops")#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;usingu64=unsignedlonglong;usingPII=p......
  • C140 线段树分治+01Trie P4585 [FJOI2015] 火星商店问题
    视频链接:   C09【模板】可持久化字典树(Trie)-董晓-博客园(cnblogs.com)P4585[FJOI2015]火星商店问题-洛谷|计算机科学教育新生态(luogu.com.cn)//线段树分治O(nlognlogn)#include<iostream>#include<cstring>#include<algorithm>#include<vect......
  • 线段树进阶
    P5787二分图/【模板】线段树分治普通二分图:染色染色无法扩展,先考虑加边如果两点在同一联通块内:加边只需要考虑连边的两个点颜色是否相同如果不在同一联通块内,第一次加边为YES,合并联通块,接下来的操作同上再考虑删边线段树分治思想解决问题:容易插入,难删除,且插入顺序不影响......
  • 线段树进阶 学习笔记
    线段树合并学习笔记线段树分治P5787考虑怎么判断二分图。先考虑弱化的版本。不考虑删边加边,则可以直接黑白染色。考虑只加边,不删边,分类讨论:注意到对于同一个连通块,一共只有两种染色方式。加的边在两个连通块之间,一定是Yes,并确定了两个连通块的染色方案。加的边在连通......
  • 动态开点线段树
    众所周知,线段树要开\(4\)倍空间,但是这样会浪费许多空间,所以动态开点线段树就诞生了。动态开点线段树适用于\(n\)比较大的情况,它没有优化时间复杂度,优化的是空间复杂度。具体的,我们不再用\(p\times2\)和\(p\times2+1\)作为\(p\)的左右儿子了,而用两个数组\(ls_{p}\)......
  • dp板子
    01背包f[x]表示装x重量时最大价值,f初值0;n物品数量,m最大重量。w表示容量,v时价值for(inti=1;i<=n;i++)//物品{for(intj=m;j>=w[i];j--){//容量f[j]=max(f[j],f[j-w[i]]+v[i]);}}完全背包for(inti=0;i<=m;i++){//背包容量for(intj=1;j<=n;j++){//物品数量if(i......
  • 重链剖分与线段树
    树链剖分将整棵树可以铺到线性的去维护,于是利用线段树等可维护线性数组的数据结构,就可以做到很多事情了当然也包括省赛的J题--奇偶最小生成树,并且线段树还支持修改操作,这是ST表与普通倍增维护做不到的这是没有模数的代码:intn,m;llw[N];inthead[N],cnt;structE......
  • C138 线段树分治 P2056 [ZJOI2007] 捉迷藏
    视频链接:C138线段树分治P2056[ZJOI2007]捉迷藏_哔哩哔哩_bilibili   P2056[ZJOI2007]捉迷藏-洛谷|计算机科学教育新生态(luogu.com.cn)//线段树分治O(nlognlogn)#include<iostream>#include<cstring>#include<algorithm>#include<vector>#inclu......
  • 线段树学习笔记
    线段树(SegmentTree)是一种基于分治思想的数据结构,可以在\(\mathcal{O}(\log~n)\)的时间内完成区间修改和区间查询等操作。1.1线段树基础此部分介绍普通线段树的基本思想与操作。1.1.1基本思想线段树本质上就是一棵二叉树,它的每一个节点表示一段区间的信息,对于一个长度不为......