「JOISC 2019 Day2」两个天线(线段树)

https://loj.ac/problem/3033

题解:

这题的线段树维护有点妙。

\(|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]);
}
posted @ 2020-03-04 16:52  Cold_Chair  阅读(580)  评论(0编辑  收藏  举报