「板子」线段树维护单调栈
记一下线段树维护单调栈的板子,学的是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;
}
$$We're \; here \; to \; put \; a \; dent \; in \; the \; universe.$$