Segment Tree Beats 小记

Segmentree beats!---吉如一线段树学习笔记 jry老师太牛了!! 本文为学习吉如一老师 Segmenttree beats 一文后有感而发qwq I 给定一个长度为n的数列A,接下来有m次操作: • 区间[l,r][l,r][l,r]中的所有数变成min(Ai,x)min(Ai,x)min(Ai,x) • 询问区间[l,r][l,r][l,r]中所有数的和 记录区间最大值和次大值,如果小于次大值就暴力递归即可 证明: 会发现我们每次花费O(log⁡n)O(\log n)O(logn)的时间使得两个数变得相同,因此总复杂度就是O(mlog⁡n+nlog 阅读详情

就拿洛谷的模板题来举例吧。


我们先简化一下各个操作的定义:

操作 1 1 1:区间加 k k k;

操作 2 2 2:区间同 v v v 取 min ⁡ \min min;

操作 3 3 3:区间求和;

操作 4 4 4:区间求最大值;

操作 5 5 5:区间求最大的历史最大值。

其中操作 2 2 2 和 5 5 5 是比较复杂的,所以我们需要用到吉老师发明的线段树—— S e g m e n t   T r e e   B e a t s Segment~Tree~Beats Segment Tree Beats。

(注:所有的操作通过势能分析法可得总时间复杂度为 O ( m l o g 2 n ) O(m log_2 n) O(mlog2​n),具体证明可以参考原论文)

(显然是笔者太菜了不会)


在分析操作之前,我们定义一些变量(指线段树节点上储存的变量):

(强烈建议拿草稿纸记录一下)

s u m a suma suma —— 区间内 A i A_i Ai​ 的和;

m x a mxa mxa —— 区间内 A i A_i Ai​ 的最大值;

c n t m x cntmx cntmx —— 区间内 A i A_i Ai​ 最大值的出现次数(方便求和时最大值与其它值分别计算);

c m x a cmxa cmxa —— 区间内 A i A_i Ai​ 的严格次大值(这个在操作 2 2 2 中会用到,实质是为了维护 c n t m x cntmx cntmx);

m x b mxb mxb —— 区间内 B i B_i Bi​ 的最大值;

然后再定义一些标记(同上):

t a g a m x tagamx tagamx —— 区间内 A i A_i Ai​ 的最大值的加法标记;

t a g a n m x taganmx taganmx —— 区间内非 A i A_i Ai​ 最大值的加法标记;

t a g b m x tagbmx tagbmx —— 注意这并不是区间内 B i B_i Bi​ 的最大值的加法标记,这是区间的 t a g a m x tagamx tagamx 的历史最大值(历史指上一次 P u s h d o w n Pushdown Pushdown 之后);

t a g b n m x tagbnmx tagbnmx —— 同上,这是区间的 t a g a n m x taganmx taganmx 的历史最大值。

为什么 t a g b m x tagbmx tagbmx 是 t a g a m x tagamx tagamx 的历史最大值?

比如有一个变量 v a l val val,在下一次 P u s h d o w n Pushdown Pushdown 前进行了两次加法操作:一次加 5 5 5,一次减 2 2 2,那么 t a g a m x tagamx tagamx 的历史最大值应当为 5 5 5,此时 v a l val val 才更有可能成为历史最大值。


然后我们来分析一下线段树的 P u s h u p , U p d a t e , P u s h d o w n Pushup,Update,Pushdown Pushup,Update,Pushdown 三个操作。

首先是 P u s h u p Pushup Pushup,大力维护即可。

代码:

inline void Pushup(int now)
{
	suma[now] = suma[ls] + suma[rs];
	mxa[now] = max(mxa[ls], mxa[rs]);
	mxb[now] = max(mxb[ls], mxb[rs]);
	if(mxa[ls] == mxa[rs])
	{
		cntmx[now] = cntmx[ls] + cntmx[rs];
		cmxa[now] = max(cmxa[ls], cmxa[rs]);
		return;
	}
	if(mxa[ls] > mxa[rs])
	{
		cntmx[now] = cntmx[ls];
		cmxa[now] = max(cmxa[ls], mxa[rs]);
	}
	else
	{
		cntmx[now] = cntmx[rs];
		cmxa[now] = max(mxa[ls], cmxa[rs]);
	}
	return;
}

然后是 U p d a t e Update Update,它的函数框架应该是这样的:

inline void Update(int now, int l, int r, LL pamx, LL panmx, LL pbmx, LL pbnmx)

( p p p 前缀代指 p l u s plus plus,即需要加的数)

首先维护 s u m a suma suma,用 p a m x pamx pamx 与 c n t m x cntmx cntmx 配合维护即可。

其次,我们要维护 m x b , t a g b m x , t a g b n m x mxb,tagbmx,tagbnmx mxb,tagbmx,tagbnmx 三个和 B i B_i Bi​ 有关的变量。

为什么呢?因为它们的维护与 A i A_i Ai​ 关系密切,而后面的操作会改变和 A i A_i Ai​ 有关的变量。

对于 m x b mxb mxb,我们把它和 m x a + p b m x mxa + pbmx mxa+pbmx 取最大值,后者即为上文所提到的“历史最大值的可能值”。

对于 t a g b m x tagbmx tagbmx,我们把它和 t a g a m x + p b m x tagamx + pbmx tagamx+pbmx 取最大值,原理同上。

同理,对于 t a g b n m x tagbnmx tagbnmx,我们把它和 t a g a n m x + p b n m x taganmx + pbnmx taganmx+pbnmx 取最大值即可。

然后和 A i A_i Ai​ 有关的变量维护起来就没那么麻烦了,直接加即可,注意判断 c m x a cmxa cmxa 的有无。

代码:

inline void Update(int now, int l, int r, LL pamx, LL panmx, LL pbmx, LL pbnmx)
{
	suma[now] += pamx * cntmx[now] + panmx * (r - l + 1 - cntmx[now]);
	mxb[now] = max(mxb[now], mxa[now] + pbmx);
	tagbmx[now] = max(tagbmx[now], tagamx[now] + pbmx);
	tagbnmx[now] = max(tagbnmx[now], taganmx[now] + pbnmx);
	mxa[now] += pamx, tagamx[now] += pamx, taganmx[now] += panmx;
	if(cmxa[now] != -INF) cmxa[now] += panmx;
	return;
}

写出了 U p d a t e Update Update,其实 P u s h d o w n Pushdown Pushdown 也很好写了。

只要你真正理解了上述变量的含义,相信你看懂甚至独立写出下述代码都会易如反掌。

(注意左右儿子的 m x a mxa mxa 最大值要保存起来)

inline void Pushdown(int now, int l, int r)
{
	int mxn = max(mxa[ls], mxa[rs]);
	if(mxa[ls] == mxn) Update(ls, l, mid, tagamx[now], taganmx[now], tagbmx[now], tagbnmx[now]);
	else Update(ls, l, mid, taganmx[now], taganmx[now], tagbnmx[now], tagbnmx[now]);
	if(mxa[rs] == mxn) Update(rs, mid + 1, r, tagamx[now], taganmx[now], tagbmx[now], tagbnmx[now]);
	else Update(rs, mid + 1, r, taganmx[now], taganmx[now], tagbnmx[now], tagbnmx[now]);
	return tagamx[now] = taganmx[now] = tagbmx[now] = tagbnmx[now] = 0LL, void();
}

接下来我们分析一下每个操作。

首先是操作 1 1 1。

这是线段树的基本操作,可以直接做。

在 U p d a t e Update Update 函数中,我们对所有量一视同仁,加法标记(指函数参数)全部赋为 k k k。

代码:

inline void Modify_Plus(int now, int l, int r, int L, int R, LL k)
{
	if(L <= l && r <= R) return Update(now, l, r, k, k, k, k);
	Pushdown(now, l, r);
	if(L <= mid) Modify_Plus(ls, l, mid, L, R, k);
	if(R > mid) Modify_Plus(rs, mid + 1, r, L, R, k);
	return Pushup(now);
}

接着分析一下操作 2 2 2。

我们对 v v v 分类讨论:(以下区间指线段树递归时遍历到的区间)

  1. 如果 v ≥ m x a v \ge mxa v≥mxa,那么该操作不会有任何影响,直接跳过该区间即可;
  2. 如果 c m x a < v < m x a cmxa < v < mxa cmxa<v<mxa,那么该操作只会改变最大值,不会改变 c n t m x cntmx cntmx;
  3. 如果 v ≤ c m x a v \le cmxa v≤cmxa,那么我们继续递归下去(线段树的叶子节点不会出现这种情况)。

对于最大值,加法标记即为 k − m x a k - mxa k−mxa(减去 m x a mxa mxa 加上 k k k,也就是把 m x a mxa mxa 赋为 k k k);对于非最大值,这样的修改不会有贡献,即加法标记为 0 0 0。

代码:

inline void Modify_Minimize(int now, int l, int r, int L, int R, LL k)
{
	if(k >= mxa[now]) return;
	if(L <= l && r <= R && k > cmxa[now]) return Update(now, l, r, k - mxa[now], 0, k - mxa[now], 0);
	Pushdown(now, l, r);
	if(L <= mid) Modify_Minimize(ls, l, mid, L, R, k);
	if(R > mid) Modify_Minimize(rs, mid + 1, r, L, R, k);
	return Pushup(now);
}

操作 3 , 4 , 5 3,4,5 3,4,5 实际上是同普通的线段树完全一样的套路。

代码:

inline LL Query_Sum(int now, int l, int r, int L, int R)
{
	if(L <= l && r <= R) return suma[now];
	Pushdown(now, l, r);
	LL res = 0LL;
	if(L <= mid) res += Query_Sum(ls, l, mid, L, R);
	if(R > mid) res += Query_Sum(rs, mid + 1, r, L, R);
	return res;
}

inline LL Query_Maximum_A(int now, int l, int r, int L, int R)
{
	if(L <= l && r <= R) return mxa[now];
	Pushdown(now, l, r);
	LL res = -INF;
	if(L <= mid) res = max(res, Query_Maximum_A(ls, l, mid, L, R));
	if(R > mid) res = max(res, Query_Maximum_A(rs, mid + 1, r, L, R));
	return res;
}

inline LL Query_Maximum_B(int now, int l, int r, int L, int R)
{
	if(L <= l && r <= R) return mxb[now];
	Pushdown(now, l, r);
	LL res = -INF;
	if(L <= mid) res = max(res, Query_Maximum_B(ls, l, mid, L, R));
	if(R > mid) res = max(res, Query_Maximum_B(rs, mid + 1, r, L, R));
	return res;
}

当然还有 B u i l d Build Build 函数,放总代码里啦。

总代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cassert>
#include<algorithm>

#define MAXN 500005

using LL = long long;
using namespace std;

int n, m;
const LL INF = 0x3F3F3F3F3F3F3F3F;

namespace Segment_Tree_Beats
{
	#define ls (now << 1)
	#define rs (now << 1 | 1)
	#define mid ((l + r) >> 1)
	
	int cntmx[MAXN << 2];
	LL suma[MAXN << 2], mxa[MAXN << 2], cmxa[MAXN << 2], mxb[MAXN << 2], tagamx[MAXN << 2], taganmx[MAXN << 2], tagbmx[MAXN << 2], tagbnmx[MAXN << 2];

	inline void Pushup(int now)
	{
		suma[now] = suma[ls] + suma[rs];
		mxa[now] = max(mxa[ls], mxa[rs]);
		mxb[now] = max(mxb[ls], mxb[rs]);
		if(mxa[ls] == mxa[rs])
		{
			cntmx[now] = cntmx[ls] + cntmx[rs];
			cmxa[now] = max(cmxa[ls], cmxa[rs]);
			return;
		}
		if(mxa[ls] > mxa[rs])
		{
			cntmx[now] = cntmx[ls];
			cmxa[now] = max(cmxa[ls], mxa[rs]);
		}
		else
		{
			cntmx[now] = cntmx[rs];
			cmxa[now] = max(mxa[ls], cmxa[rs]);
		}
		return;
	}

	inline void Update(int now, int l, int r, LL pamx, LL panmx, LL pbmx, LL pbnmx)
	{
		suma[now] += pamx * cntmx[now] + panmx * (r - l + 1 - cntmx[now]);
		mxb[now] = max(mxb[now], mxa[now] + pbmx);
		tagbmx[now] = max(tagbmx[now], tagamx[now] + pbmx);
		tagbnmx[now] = max(tagbnmx[now], taganmx[now] + pbnmx);
		mxa[now] += pamx, tagamx[now] += pamx, taganmx[now] += panmx;
		if(cmxa[now] != -INF) cmxa[now] += panmx;
		return;
	}

	inline void Pushdown(int now, int l, int r)
	{
		int mxn = max(mxa[ls], mxa[rs]);
		if(mxa[ls] == mxn) Update(ls, l, mid, tagamx[now], taganmx[now], tagbmx[now], tagbnmx[now]);
		else Update(ls, l, mid, taganmx[now], taganmx[now], tagbnmx[now], tagbnmx[now]);
		if(mxa[rs] == mxn) Update(rs, mid + 1, r, tagamx[now], taganmx[now], tagbmx[now], tagbnmx[now]);
		else Update(rs, mid + 1, r, taganmx[now], taganmx[now], tagbnmx[now], tagbnmx[now]);
		return tagamx[now] = taganmx[now] = tagbmx[now] = tagbnmx[now] = 0LL, void();
	}

	inline void Build(int now, int l, int r)
	{
		if(l == r)
		{
			LL k; scanf("%lld", &k);
			return suma[now] = mxa[now] = mxb[now] = k, cntmx[now] = 1, cmxa[now] = -INF, tagamx[now] = taganmx[now] = tagbmx[now] = tagbnmx[now] = 0LL, void();
		}
		return Build(ls, l, mid), Build(rs, mid + 1, r), Pushup(now);
	}

	inline void Modify_Plus(int now, int l, int r, int L, int R, LL k)
	{
		if(L <= l && r <= R) return Update(now, l, r, k, k, k, k);
		Pushdown(now, l, r);
		if(L <= mid) Modify_Plus(ls, l, mid, L, R, k);
		if(R > mid) Modify_Plus(rs, mid + 1, r, L, R, k);
		return Pushup(now);
	}

	inline void Modify_Minimize(int now, int l, int r, int L, int R, LL k)
	{
		if(k >= mxa[now]) return;
		if(L <= l && r <= R && k > cmxa[now]) return Update(now, l, r, k - mxa[now], 0, k - mxa[now], 0);
		Pushdown(now, l, r);
		if(L <= mid) Modify_Minimize(ls, l, mid, L, R, k);
		if(R > mid) Modify_Minimize(rs, mid + 1, r, L, R, k);
		return Pushup(now);
	}

	inline LL Query_Sum(int now, int l, int r, int L, int R)
	{
		if(L <= l && r <= R) return suma[now];
		Pushdown(now, l, r);
		LL res = 0LL;
		if(L <= mid) res += Query_Sum(ls, l, mid, L, R);
		if(R > mid) res += Query_Sum(rs, mid + 1, r, L, R);
		return res;
	}

	inline LL Query_Maximum_A(int now, int l, int r, int L, int R)
	{
		if(L <= l && r <= R) return mxa[now];
		Pushdown(now, l, r);
		LL res = -INF;
		if(L <= mid) res = max(res, Query_Maximum_A(ls, l, mid, L, R));
		if(R > mid) res = max(res, Query_Maximum_A(rs, mid + 1, r, L, R));
		return res;
	}

	inline LL Query_Maximum_B(int now, int l, int r, int L, int R)
	{
		if(L <= l && r <= R) return mxb[now];
		Pushdown(now, l, r);
		LL res = -INF;
		if(L <= mid) res = max(res, Query_Maximum_B(ls, l, mid, L, R));
		if(R > mid) res = max(res, Query_Maximum_B(rs, mid + 1, r, L, R));
		return res;
	}
	#undef ls
	#undef rs
	#undef mid
}

namespace stb = Segment_Tree_Beats;

int main()
{
	#ifdef FILE
		freopen("Input.in", "r", stdin);
	#endif
	scanf("%d%d", &n, &m);
	stb :: Build(1, 1, n);
	while(m--)
	{
		int opt, l, r; scanf("%d%d%d", &opt, &l, &r);
		if(opt == 1)
		{
			LL k; scanf("%lld", &k);
			stb :: Modify_Plus(1, 1, n, l, r, k);
			continue;
		}
		if(opt == 2)
		{
			LL k; scanf("%lld", &k);
			stb :: Modify_Minimize(1, 1, n, l, r, k);
			continue;
		}
		if(opt == 3) printf("%lld\n", stb :: Query_Sum(1, 1, n, l, r));
		if(opt == 4) printf("%lld\n", stb :: Query_Maximum_A(1, 1, n, l, r));
		if(opt == 5) printf("%lld\n", stb :: Query_Maximum_B(1, 1, n, l, r));
	}
	return 0;
}

E N D \mathit{END} END

吉司机线段树(segment tree beats!) sdoir1考挂,本来都要退役了。。。结果还是进了二轮末尾。。。打算混个D类去养老; 最近有点颓,需要写些东西和学些新东西止一下颓势,就先把这几星期前学的神奇线段树写了吧。。。 吉司机线段树主要是用来解决序列区间上满足部分满足一定性质的修改操作的,比方说把区间中小于x的数改成x,大于x的数改成x,甚至是区间取并和区间取或(实际上也就是区间中的每个数的每一位进行类似小于x改成x那种操作) 这玩... 阅读详情

相关推荐

arduino esp8266_Arduino传感器教程 第22章ESP8266 控制 5V 继电器

ESP8266控制5V继电器目录一、NodeMCU二、工作原理本文将使用亚马逊 AlexaEcho 和 ESP8266 控制 5V 继电器。NodeMCUNodeMCU 是一个开源的 IoT 物联网硬件开发板,由于它支持 WIFI 功能且使用方法十分类似 Arduino 开发板,所以近些年获得了越来越多来自全世界的创客朋友们的青睐。NodeMCU 尺寸与 Arduino Nano 类似。...

weixin_39611722的博客 3455

Segment Tree Beats(吉司机线段树)

1 给出 nnn 个数,qqq 次询问,求最大子段和,相同的数只算一次。(GSS2) 在线不是很好做,我们离线下来,把询问按 rrr 升序排序,线段树上维护每个 lll 到 rrr 的和。如果预处理出每个数上一个出现的位置 pre[i]pre[i]pre[i],那么每次右端点右移相当于区间 [pre[i]+1,r][pre[i]+1,r][pre[i]+1,r] 加 a[i]a[i]a[i],查询...

Hellsegamosken 3846

SAP采购订单中项目类别B(限制)的控制逻辑

在笔者所在企业中,框架类采购订单中项目类别需要选择B(限制)。今天笔者从比较全面的角度分析了一下这个项目类别B到底可以决定些什么?控制到什么?先从后台SPRO中打开相应的配置菜单。 打开项目类别B之后,可以看到一些配置信息,这里有一点与其它配置不同的地方,即无法新增项目,也无法修改现有项目。这个疑惑今后再去解决吧。当前只研究项目类别B的控制逻辑。 下面就参考上图中的配置分段来分析和测试其控制逻辑, 1、如项目类别配置图,所需材料值为不允许;经测试,如下图在采购订单创建时,不能输入物料编号条目。

专注SAP应用技术文章写作,致力于拉近用户与系统间的距离; 6032

Segment tree beats(吉老师线段树)学习笔记

区间最值操作 区间最值操作,指的是对区间 [l,r][l,r][l,r] 里的全部数对 xxx 取 min⁡\minmin 或取 max⁡\maxmax,即 ai=min⁡(ai,x)a_i=\min(a_i,x)ai​=min(ai​,x) 或 ai=max⁡(ai,x)a_i=\max(a_i,x)ai​=max(ai​,x)。 一道例题 HDU5306 Gorgeous Sequence 我们用线段树维护每个区间的最大值 mxmxmx 和严格次大值 sesese,以及 mxmxmx 的个数 cntc

hipamp的博客 1862

使用 Java + PaddleOCR 实现表格识别,支持导出 HTML 和 Excel(附源码)

使用Java+PaddleOCR快速搭建表格识别系统,无需处理底层模型细节。系统支持表格结构识别和内容识别,可将图片转换为可编辑表格格式。文章提供了完整的实现流程,包括Maven依赖引入、模型下载(包含检测、识别、分类和表格结构模型)及参数配置说明。SmartJavaAI支持多种高性能模型选择,适用于不同应用场景,帮助开发者快速实现表格识别功能。

deng775747758的博客 1473

UE5.3.2 + VS2022社区版在Win11上的C++编译环境配置全解

Unreal Engine 5的C++开发依赖严格的工具链协同,其核心在于Visual Studio编译器版本、Windows SDK与引擎构建系统(UBT)的精准匹配。UE5.3.2强制要求MSVC v143.4(即VS2022 17.4+)及Windows 11 SDK 10.0.22621.0,任何偏差都会引发LNK2019链接失败、C1083头文件缺失或MSB8066构建中断等典型错误。该配置不仅关乎安装顺序,更涉及注册表清理、PATH环境变量、SDK路径注入与运行时DLL加载等底层机制。适用于Wi

weixin_33978722的博客 367

Segment tree beats~

Segment tree beats! 旨在练习 吉老师线段树,并且存个板子~ #576 (Div. 2) D. Welfare State 区间取 maxmaxmax 的裸题,对于取 maxmaxmax 操作,维护最小值、次小值、最小值次数,通过加标记的方式就能维护 取 maxmaxmax 操作了; 区间取 minminmin 的操作 与之类似。 #include<bits/stdc++.h> using namespace std; inline int qread(){ int

qq_52383696的博客 387

深度解析与实战:长短时记忆网络(LSTM)在股票走势预测中的应用(基于Python + PyTorch)

本文全面探讨了LSTM在股票价格预测中的应用,从理论基础到实践操作。文章首先强调了股票市场预测的重要性,并介绍了LSTM网络结构及其在处理时间序列数据中的优势。接着,详细说明了数据预处理的关键步骤,包括数据收集、清洗、特征选择和归一化。文章还讨论了LSTM模型的构建、训练和评估,并提供了Python及PyTorch的实操案例。最后,总结了LSTM在股票预测的成果,并提出了未来研究的方向,如模型优化和特征工程,旨在帮助读者掌握LSTM在股票价格预测中的应用,并探索提升模型性能的方法。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 2100

BZOJ 4695: 最假女选手 segment-tree-beats

新学 segment-tree-beats. 这道题在区间取 min/max 的基础上还有一个区间加,那么显然要先做区间加,再取 min/max. code: // bzoj 最假女选手 #include <cstdio> #include <algorithm> #include <cstring> ...

EM LGH 231

STM32CubeIDE开发环境搭建与GPIO控制实战

嵌入式开发中,MCU开发环境构建是软硬件协同的起点,其核心在于工具链选型、外设抽象层级与调试可靠性。HAL库作为ST官方标准硬件抽象层,通过统一接口屏蔽芯片差异,显著提升工程可移植性;而STM32CubeIDE则以图形化配置+自动生成代码的方式,实现‘配置即代码’的确定性开发范式。该组合在教学验证、原型迭代和中小规模量产中具备高性价比技术价值,广泛应用于智能传感、工业HMI及IoT终端等场景。本文聚焦STM32CubeIDE 1.15.0环境部署、MyST账户与固件包管理、ST-LINK驱动校验,以及基于H

weixin_33531560的博客 79

18、深入解析航空飞行数据中的秘密:从数据清理到高级分析

本文详细解析了如何使用R语言处理和分析航空飞行数据,从基础的数据清理到复杂的回归分析和机器学习模型构建。文章涵盖了探索性数据分析、天气数据的整合、地理信息可视化、时间序列预测以及航班延误的优化策略等内容,展示了如何通过数据挖掘技术提高航空运营效率和乘客满意度,并探讨了数据质量评估与隐私保护的重要性。

convnet3designer的博客 106

BZOJ.4695.最假女选手(线段树 Segment tree Beats!)

题目链接 区间取\(\max,\ \min\)并维护区间和是普通线段树无法处理的。 对于操作二,维护区间最小值\(mn\)、最小值个数\(t\)、严格次小值\(se\)。 当\(mn\geq x\)时,不需要改变,return;\(se>x>mn\)时,\(sum=sum+(x-mn)*t\),打上区间\(\max\)标记; 当\(x\geq se>mn\)时,不会做,继续递归分...

weixin_30569001的博客 278

22、狭义相对论与曲线坐标空间相关知识解析

本文深入解析了狭义相对论与曲线坐标空间的核心概念,涵盖能量-动量张量的定义与守恒、曲线坐标系下的度量张量与基向量性质、协变与逆变张量的变换规则,并介绍了克里斯托费尔符号与协变导数的计算方法。进一步探讨了在弯曲空间中进行微积分运算的基础理论及其在广义相对论中的关键应用,如爱因斯坦场方程如何描述物质-能量对时空曲率的影响,为理解黑洞等引力现象提供了理论框架。

lambda的博客 115

吉司机线段树,segment tree beats

线段树的查询操作:线段树的查询操作主要是通过搜索适当的区间来获得所需的信息。线段树是一种用于解决区间查询问题的数据结构,它将一个区间划分为多个子区间,并对每个子区间维护一些有用的信息,例如最大值、最小值、和等等。线段树的构建:构建线段树时,需要考虑边界条件。通常情况下,线段树的叶子节点对应于原始输入数组的元素,因此线段树的构建过程涉及到对叶子节点的赋值。例如,对于求区间和的问题,每个节点的信息就是其左子节点的和加上右子节点的和。线段树的更新操作:线段树的更新操作主要包括对叶子节点的更新以及对父节点的更新。

2301_79894597的博客 877

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Segment Tree Beats 学习笔记

模板题: hdu5306 维护最大值,最大值个数,次大值,区间和即可。 区间更新k的时候,若当且节点最大值小于k则直接返回,k小于最大值且大于次大值时则可以直接更新区间和和最大值,否则继续递归左右儿子,注意要把信息更新到当前节点的所有祖先节点。 节点信息向下传递的时候,祖先的历史最小值显然大于等于当前的次小值,所以只要祖先的历史最小值小于当前节点的最大值,就要把当前节点更新一下。 #include...

pubgoso的博客 1819

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Segment Tree Beats 区间最值问题

Segment Tree Beats 区间最值问题 线段树一类特殊技巧! 引出:CF671C Ultimate Weirdness of an Array 其实是考试题,改题的时候并不会区间取最值,区间求和,之后秉承着好好学习的态度,学习了Segment tree Beats 套路是维护出区间最小值和次小值,以及区间最小值数量。之后再维护出题目中需要的东西就好了。之后怎么处理呢,如果我们需...

weixin_33790053的博客 233

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

线段树 (Segment Tree) 完全指南

线段树(Segment Tree)是一种对线性空间的"二进制拆分"思想。如果说前缀和是利用了加法的逆运算,那么线段树就是利用了结合律的终极武器。 线段树的本质是分治法(Divide and Conquer)在空间上的持久化。 结合律意味着计算顺序可以被改变,从而允许我们将线性的计算重组为树形结构。如果直接操作不满足结合律(如"求众数"),就需要构造更复杂的信息结构使其满足(如摩尔投票法的合并)。所有的线段树高级技巧(Level 1-6),本质上都是在寻找或构造这个结合律。

lifallen的博客 1142

【ARC082F】Sandglass【线段树】

我们可以首先把所有询问按时间排序,然后维护一棵以初始沙子数量为下标的线段树。把反转操作依次进行,相当于区间加减,然后区间对0取max,对x取min。这些可以简单地通过线段树实现。在执行操作的过程中询问答案。但是下标有10910910^9的范围,怎么办?我们动态开点就好。 #include&amp;lt;bits/stdc++.h&amp;gt; using namespace std; const int N=...

2016gdgzoi471 299

HDU 5306 Gorgeous Sequence, Segment Tree Beats

    常规的线段树可以用lazy标志来实现线段树的区间更新(区间覆盖,区间加减定值等),但是形如下面操作1却不是很好处理For all , change Ai to min(Ai, x)Query for the sum of Ai in [l, r]        可以参考2016年国家集训队论文集中的“区间最值与历史最值问题”——吉如一,关于求区间和、区间最值的问题可以用常规的线段树轻松解决...

Sothan 623

关于log方线段树

通常,线段树是一个log的。 但是,有的用于解决特殊问题的线段树,是两个log的。 这个额外的log有两种情况: 第一种就是添加的标记比较特殊,使得pushdown时可能递归。 通过诡异证明,使得均摊复杂度为\(O(nlog^2n)\)。 第二种就是pushup时,需要递归到其中一个子树,这样每次pushup是\(O(logn)\)的,总复杂度\(O(nlog^2n)\)。 第一种 李超...

weixin_42465242的博客 340

[学习笔记]Segment Tree Beats!九老师线段树

对于这样一类问题: 区间取min,区间求和。 N<=100000 要求O(nlogn)级别的算法 直观体会一下,区间取min,还要维护区间和 增加的长度很不好求。。。。 然鹅, 从前有一个来自杭州天水幼儿园的julao叫九条可怜 他发明了一个线段树的写法, 攻克了这个难题。 说起来很简单: 线段树维护区间最大值,区间严格次大值,和区间最大值出现次数 ...

weixin_33860528的博客 269

[学习笔记] [UR #11]元旦老人与数列 - segment tree beats学习笔记

首先对于区间对d取max操作可以认为是,如果d小于等于最小值那么没有影响;如果d大于等于严格次大值那么去递归左右儿子,然后push_up出这个节点的信息;因此真正意义上修改这个区间的情况是d介于最小值和严格次小值之间,这时候相当于只把区间中的最小值加上一些数字。也就是说,最小值的维护要和其余数字的维护分开来。 线段树维护: mn表示区间最小值,se表示区间严格次小值(若没有就是INF); p...

Mys_C_K的博客 618

[线段树 区间最值操作 模板 Segment tree Beats!] BZOJ 4695 最假女选手

鬼畜线段树的大模板题 具体见吉丽的集训队论文 我终于会写线段树了 不对 我好像还不会历史最值#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; typedef long long ll;inline char nc(){ static char buf[100000],*p1=buf,*p2=b

雯舞 1871

[Segment tree Beats! || 分块] Codeforces 793F Tinkoff Challenge - Elimination Round F. Julia the snail

我们用fif_i表示左边界是ii的答案 一条线段[a,b][a,b]对答案的影响是 f1f_1到flf_l中大于等于aa的都跟bb取max 这个可以用线段树科技做 复杂度证明跟区间最值操作的势能分析应该差不多#include<cstdio> #include<cstdlib> #include<algorithm> #include<cassert> using namespace std;inl

雯舞 1351

Segment Tree 线段树总结

1.何为线段树 准确的来说,线段树是一种平衡二叉树,当我们的要换分的区间大小是2的幂的话,刚好我们的线段树就是一颗满二叉树,但是如果不是的话,我们最多只能叫他是平衡二叉树 正因为是一颗平衡二叉树,所以说,线段树的划分是均匀的,树高也稳定在logn上(这也就是我们的优化的源泉) 上面只是个人的一点小理解,下面我们步入正题 线段树Segment Tree,是BST二叉搜索树而一种应用,

72 73 76 89 82 84 89 81 2658
上一篇: P4224 [清华集训2017]简单数据结构 题解
下一篇: OI数学小记
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值