「板子」线段树维护单调栈

记一下线段树维护单调栈的板子,学的是Deepinc版本。

板子只是维护单调下降的序列,但只要把序列倒过来,不就变成了单调上升的了么233

陶陶摘苹果

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n, m;
int a[maxn];
struct tree {
	int mx, lv, l, r;
}t[maxn << 2];
int maxr; // maxr记录当前节点右区间的最大值
#define ls (u << 1)
#define rs (u << 1 | 1)
int Ask(int u, int ql, int qr, int x) {
	if (x >= t[u].mx) return 0;
	if (t[u].l == t[u].r) {
		maxr = max(maxr, t[u].mx);
		return 1;
	}
	if (ql <= t[u].l && t[u].r <= qr) {
		if (x > t[rs].mx) return Ask(ls, ql, qr, x);
		int tmp = Ask(rs, ql, qr, x) + t[u].lv;
		maxr = max(maxr, t[u].mx);
		return tmp;
	}
	int mid = (t[u].l + t[u].r) >> 1;
	int ans = 0;
	if (qr > mid) ans += Ask(rs, ql, qr, x); // 先查右区间
	if (ql <= mid) ans += Ask(ls, ql, qr, maxr); // 用右区间砍左区间
	return ans;
}
void Pushup(int u) {
	t[u].mx = max(t[ls].mx, t[rs].mx);
	maxr = 0;
	t[u].lv = Ask(ls, t[ls].l, t[ls].r, t[rs].mx);
}
void Build(int u, int l, int r) {
	t[u].l = l;
	t[u].r = r;
	if (l == r) {
		t[u].mx = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	Build(ls, l, mid);
	Build(rs, mid + 1, r);
	Pushup(u);
	return;
}
void Modify(int u, int pos, int x) {
	if (t[u].l == t[u].r) {
		t[u].mx = x;
		return;
	}
	int mid = (t[u].l + t[u].r) >> 1;
	if (pos <= mid) Modify(ls, pos, x);
	else Modify(rs, pos, x);
	Pushup(u);
}
int main() {
	freopen("taopapp.in", "r", stdin);
	freopen("taopapp.out", "w", stdout);
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; ++i) scanf("%d", &a[n + 1 - i]); // 将序列倒过来,就变成了求递减序列
	Build(1, 1, n);
	int pos, x;
	while (m--) {
		scanf("%d %d", &pos, &x);
		pos = n + 1 - pos;
		int tmp = a[pos];
		Modify(1, pos, x);
		maxr = 0;
		printf("%d\n", Ask(1, 1, n, 0));
		Modify(1, pos, tmp);
	}
	return 0;
}

楼房重建

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n, m;
struct tree {
	double k;
	int lv, l, r;
}t[maxn << 2];
double maxr;
#define ls (u << 1)
#define rs (u << 1 | 1)
int Ask(int u, int ql, int qr, double val) {
	if (t[u].k <= val) return 0;
	if (t[u].l == t[u].r) {
		maxr = max(maxr, t[u].k);
		return 1;
	}
	if (ql <= t[u].l && t[u].r <= qr) {
		if (t[rs].k <= val) return Ask(ls, ql, qr, val);
		int tmp = Ask(rs, ql, qr, val) + t[u].lv;
		maxr = max(maxr, t[u].k);
		return tmp;
	}
	int mid = (t[u].l + t[u].r) >> 1;
	int ans = 0;
	if (qr > mid) ans += Ask(rs, ql, qr, val);
	if (ql <= mid) ans += Ask(ls, ql, qr, maxr);
	return ans;
}
void Pushup(int u) {
	t[u].k = max(t[ls].k, t[rs].k);
	maxr = 0;
	t[u].lv = Ask(ls, t[ls].l, t[ls].r, t[rs].k);
}
void Build(int u, int l, int r) {
	t[u].l = l;
	t[u].r = r;
	if (l == r) return;
	int mid = (l + r) >> 1;
	Build(ls, l, mid);
	Build(rs, mid + 1, r);
	Pushup(u);
}
void Modify(int u, int pos, double val) {
	if (t[u].l == t[u].r) {
		t[u].k = val;
		return;
	}
	if (pos <= t[ls].r) Modify(ls, pos, val);
	else Modify(rs, pos, val);
	Pushup(u);
}
int main() {
	scanf("%d %d", &n, &m);
	Build(1, 1, n);
	int x, y;
	while (m--) {
		scanf("%d %d", &x, &y);
		double tmp = 1.0 * y / x;
		x = n + 1 - x; // 同样是把序列倒过来
		Modify(1, x, tmp);
		maxr = 0;
		printf("%d\n", Ask(1, 1, n, 0));
	}
	return 0;
}
posted @ 2020-10-12 14:35  zfio  阅读(136)  评论(2编辑  收藏  举报