「JOISC 2019 Day2」两个天线(线段树)
题解:
这题的线段树维护有点妙。
\(|h[i]-h[j]|=max(h[i]-h[j],h[j]-h[i])\),所以作两遍就不用考虑绝对值了,考虑现在是\(h[j]-h[i]\)。
用线段树维护每个位置的标记, 每个位置的标记有\(p[x]、q[x]\).
考虑对于\(i,j\),首先\(j\in[i+a[i],i+b[i]]\),那么从左往右枚举\(j\)的时候,在\(i+a[i]\)处开启\(i\)处的标记\((p[i]=-h[i])\),\(i+b[i]+1\)处关闭\((p[i]=-inf)\)。
还得满足\(i\in[j-b[j],j-a[j]]\),那么在到\(j\)时,对那一个区间的\(q\)都和\(h[j]\)取\(max\)。
一个查询就是询问一个区间的历史版本的\(p[i]+q[i]\)的最大值,这个很简单。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int N = 2e5 + 5;
const int inf = 1e9;
int n, Q, h[N], a[N], b[N];
struct ask {
int l, r;
} c[N];
vector<int> q[N];
#define pb push_back
vector<int> p[N];
void Init() {
scanf("%d", &n);
fo(i, 1, n) {
scanf("%d %d %d", &h[i], &a[i], &b[i]);
if(i + a[i] <= n) p[i + a[i]].pb(i);
if(i + b[i] + 1 <= n) p[i + b[i] + 1].pb(i);
}
scanf("%d", &Q);
fo(i, 1, Q) {
scanf("%d %d", &c[i].l, &c[i].r);
q[c[i].r].pb(i);
}
}
#define i0 i + i
#define i1 i + i + 1
int mx[N * 4], t[N * 4], lz[N * 4];
int pl, pr, px;
void qmax(int i, int x) {
lz[i] = max(lz[i], x);
t[i] = max(t[i], mx[i] + lz[i]);
}
void down(int i) {
if(lz[i] > -inf) {
qmax(i0, lz[i]);
qmax(i1, lz[i]);
lz[i] = -inf;
}
}
void add(int i, int x, int y) {
if(y < pl || x > pr) return;
if(x == y) {
lz[i] = -inf; mx[i] = px;
return;
}
int m = x + y >> 1; down(i);
add(i0, x, m); add(i1, m + 1, y);
t[i] = max(t[i0], t[i1]);
mx[i] = max(mx[i0], mx[i1]);
}
void xiu(int i, int x, int y) {
if(y < pl || x > pr) return;
if(x >= pl && y <= pr) {
qmax(i, px);
return;
}
int m = x + y >> 1; down(i);
xiu(i0, x, m); xiu(i1, m + 1, y);
t[i] = max(t[i0], t[i1]);
}
void ft(int i, int x, int y) {
if(y < pl || x > pr) return;
if(x >= pl && y <= pr) {
px = max(px, t[i]);
return;
}
int m = x + y >> 1; down(i);
ft(i0, x, m); ft(i1, m + 1, y);
}
int ans[N], us[N];
void work() {
fo(i, 1, n * 4) {
t[i] = mx[i] = lz[i] = -inf;
}
fo(i, 1, n) us[i] = 0;
fo(i, 1, n) {
ff(j, 0, p[i].size()) {
int x = p[i][j];
pl = pr = x; px = us[x] ? -inf : -h[x];
add(1, 1, n);
us[x] = 1;
}
pl = i - b[i], pr = i - a[i]; px = h[i];
xiu(1, 1, n);
ff(j, 0, q[i].size()) {
int x = q[i][j];
pl = c[x].l, pr = c[x].r, px = -2 * inf;
ft(1, 1, n);
ans[x] = max(ans[x], px);
}
}
}
int main() {
Init();
fo(i, 1, Q) ans[i] = -inf;
work();
fo(i, 1, n) h[i] = inf - h[i];
work();
fo(i, 1, Q) pp("%d\n", ans[i] < 0 ? -1 : ans[i]);
}
转载注意标注出处:
转自Cold_Chair的博客+原博客地址