【笔记】主席树

挖坑,然后在这里种一棵主席树(
看了代码就很好理解了,对于单点操作只会使 logN 个节点产生变化,这样我们更新版本时,每次往下递归时都开一个新节点复制原来的信息就行了
查询的话从对应版本号的 rt[] 走
至于怎么用...嗯...

模板,静态查询区间第 K 小,权值线段树做差
原始版本的编号是 0 ,原始版本为空树

#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 200005;
const int inf = 1e9+1;
int N, M, A[MAXN], rt[MAXN];
struct segmentTree {
	#define lson ls[x]
	#define rson rs[x]
	int ls[MAXN<<5], rs[MAXN<<5], cnt[MAXN<<5], tot;
	segmentTree() {
		tot = 0;
		memset(ls, 0, sizeof(ls));
		memset(rs, 0, sizeof(rs));
		memset(cnt, 0, sizeof(cnt));
	}
	void pushup(int x) { cnt[x] = cnt[lson] + cnt[rson]; }
	void update(int &x, int pre, int l, int r, int p) { // cnt[p]++
		x = ++tot, ls[x] = ls[pre], rs[x] = rs[pre], cnt[x] = cnt[pre];
		if (l==r) cnt[x]++;
		else {
			int mid = (l + r) >> 1;
			if (mid>=p) update(lson, ls[pre], l, mid, p);
			if (mid< p) update(rson, rs[pre], mid+1, r, p);
			pushup(x);
		}		
	}
	int query(int u, int v, int l, int r, int k) {
		if (l==r) return l;
		else {
			int mid = (l + r) >> 1, sum = cnt[ls[v]] - cnt[ls[u]];
			if (sum>=k) return query(ls[u], ls[v], l, mid, k);
			else return query(rs[u], rs[v], mid+1, r, k-sum);
		}
	}
} ST;
int read()
{
	register int o = 0, oo = 0;
	register char c = getchar();
	while (c< '0' || c> '9') o |= c=='-', c = getchar();
	while (c>='0' && c<='9') o = (o<<3)+(o<<1)+(c&15), c = getchar();
	return oo ? -o : o;
}
int main()
{
	N = read(), M = read();
	for (int i=1; i<=N; i++) A[i] = read();
	for (int i=1; i<=N; i++) ST.update(rt[i], rt[i-1], -inf, inf, A[i]);
	for (; M; M--) {
		int l = read(), r = read(), k = read();
		printf("%d\n", ST.query(rt[l-1], rt[r], -inf, inf, k));
	}
} 
posted @   zrkc  阅读(33)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示