Daimayuan Online Judge 线段树1

\(n\) 个数 \(a_1, a_2, \cdots, a_n\)
支持 \(q\) 个操作:
1. 1 x d ,修改 \(a_x = d\)
2. 2 l r ,查询 \(min_{i = l}^{r} a_i\) ,并输出 \(\sum_{i = l}^{r} [a_i = min_{i = l}^{r} a_i]\)

一:\((info, +)\) 构成一个幺半群。
确定出需要维护的信息 \(Info\) 。建立线段树节点

#define ls (id>>1)
#define rs (id>>1|1)
struct Info {
	int minv, mincnt;
    Info(){}
    Info(int _minv, int _mincnt) : minv(_minv), mincnt(_mincnt) {}
};

Info operator + (const Info &l, const Info &r) { // 这里的 l r 是作用域分离,不会和其他 l r 在同一个作用域
	Info ret;
	if ( l.minv < r.minv ) ret = l;
	else if ( r.minv < l.minv ) ret = r;
	else ret = {l.minv, l.mincnt + r.mincnt};
	return ret;
}

二:初始化线段树节点,并 build 树。

struct Node {
	Info f;
} seg[N * 4];

void build(int id, int l, int r) {
	if (l == r) {
		// init seg[id].f
        seg[id].f = {a[l], 1};
        return;
	}
	int mid = ( l + r ) >> 1;
	build(ls, l, mid );
	build (rs, mid + 1, r );
	seg[id].f = seg[ls].f + seg[rs].f;
}

三:完成树的区间查询、单点修改功能

Info query(int id, int l, int r, int ql, int qr) {
	if ( l == ql && r == qr ) {
		return seg[id].f;
	}
	int mid = ( l + r ) >> 1;
	if (qr <= mid) return query(ls, l, mid, ql, qr);
	else if (ql > mid) return query(rs, mid + 1, r, ql, qr);
	else return query(ls, l, mid, ql, mid) + query(rs, mid + 1, r, mid + 1, qr);
}
void change(int id, int l, int r, int pos, int d) {
	if ( l == r ) {
		seg[id].f.minv = d;
        return;
	}
	int mid = ( l + r ) >> 1;
	if ( pos <= mid ) change(ls, l, mid, pos, d );
	else change(rs, mid + 1, r, pos, d );
	seg[id].f = seg[ id * 2 ].f + seg[ id * 2 + 1 ].f;
}

四:完成主程序框架

int main() {
	int n, q;
	std::cin >> n >> q;
	for (int i = 1; i <= n; i++) std::cin >> a[i];
	build(1, 1, n);
	for (int i = 1; i <= q; i++) {
		int typ; std::cin >> typ;
		if ( typ == 1 ) {
			int x, d; std::cin >> x >> d;
			change(1, 1, n, x, d);
		}
		else {
			int l, r; std::cin >> l >> r;
			auto ans = query(1, 1, n, l, r);
			std::cout << ans.minv << ' ' << ans.mincnt << '\n';
		}
	}
	return 0;
}

完整代码

view
#include <bits/stdc++.h>

const int N = 200005;

int a[N]; 

struct Info {
	int minv, mincnt;
};

struct Node {
	Info f;
} seg[N * 4];

Info operator + (const Info &l, const Info &r) {
	Info ret;
	if ( l.minv < r.minv ) ret = l;
	else if ( r.minv < l.minv ) ret = r;
	else ret = {l.minv, l.mincnt + r.mincnt};
	return ret;
}

void update(int id) {
	seg[id].f = seg[ id * 2 ].f + seg[ id * 2 + 1 ].f;
}

void build(int id, int l, int r) {
	if (l == r) {
		seg[id].f = {a[l], 1};
	}
	else {
		int mid = ( l + r ) >> 1;
		build( id * 2, l, mid );
		build (id * 2 + 1, mid + 1, r );
		update(id);
	}
}

Info query(int id, int l, int r, int ql, int qr) {
	if ( l == ql && r == qr ) {
		return seg[id].f;
	}
	else {
		int mid = ( l + r ) >> 1;
		if (qr <= mid) return query( id * 2, l, mid, ql, qr );
		else if (ql > mid) return query( id * 2 + 1, mid + 1, r, ql, qr );
		else return query( id * 2, l, mid, ql, mid ) + query( id * 2 + 1, mid + 1, r, mid + 1, qr );
	}
}

void change(int id, int l, int r, int pos, int d) {
	if ( l == r ) {
		seg[id].f.minv = d;
	}
	else {
		int mid = ( l + r ) >> 1;
		if ( pos <= mid ) change( id * 2, l, mid, pos, d );
		else change( id * 2 + 1, mid + 1, r, pos, d );
		update(id);
	}
}

int main() {
	int n, q;
	std::cin >> n >> q;
	for (int i = 1; i <= n; i++) std::cin >> a[i];
	build(1, 1, n);
	for (int i = 1; i <= q; i++) {
		int typ; std::cin >> typ;
		if ( typ == 1 ) {
			int x, d; std::cin >> x >> d;
			change(1, 1, n, x, d);
		}
		else {
			int l, r; std::cin >> l >> r;
			auto ans = query(1, 1, n, l, r);
			std::cout << ans.minv << ' ' << ans.mincnt << '\n';
		}
	}
	return 0;
}
posted @ 2023-08-29 21:08  03Goose  阅读(105)  评论(0)    收藏  举报