给 \(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\) 。建立线段树节点
struct Info {
int minv, mincnt;
};
struct Node {
Info f;
} seg[N * 4];
二:确定信息加法以即如何更新。封装 \(update\) ,通常情况下只需要把左右区间的信息合并。
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;
}
三:完成主程序框架
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;
}
四:完成建树、查询、单点修改
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);
}
}
完整代码
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;
}