JOISC2019 两个天线
两个天线
不失一般性假设 \(x < y\),然后对于 \(|H_x - H_j|\),可以先算一次不带绝对值的,然后取反再算一次不带绝对值的取最大值。
考虑对于一个天线 \(y\),他能发送消息的天线范围是确定的为 \([y - B_y, y - A_y]\),但是还得要求 \(x \in [y - B_y, y - A_y]\) 的 \(y \in [x + A_x, x + B_x]\)。
于是考虑扫描线,将 \(x\) 拆成 \(x + A_x\) 和 \(x + B_x + 1\) 分别表示从此刻开始能用,从此刻开始不可用。
然后枚举 \(y\),能够互通的信号塔就是 \([y - B_y, y - A_y]\) 内所有可用的信号塔。
维护 \(d_x\) 表示每个 \(x\) 作为左边信号塔产生的最大代价,那么每次新加入一个 \(y\) 就会将 \([y - B_y, y - A_y]\) 内所有可用的信号塔的 \(d_x\) 对 \(H_x - H_y\) 取 \(\max\),询问答案就是 \(\max_{l \leq i \leq r} d_i\)。
可以对每个信号塔定义一个 \(c_i\),当其可用时 \(c_i = H_i\),否则 \(c_i = - \infty\)。
那么每个信号塔的两个事件就是对 \(c\) 的单点修改,假如一个 \(y\),就是将区间内的 \(d_i\) 对 \(c_i - H_y\) 取 \(\max\),答案仍然为 \(\max_{l \leq i \leq r} d_i\)。
线段树维护即可,没了。
// 德丽莎你好可爱德丽莎你好可爱德丽莎你好可爱德丽莎你好可爱德丽莎你好可爱
// 德丽莎的可爱在于德丽莎很可爱,德丽莎为什么很可爱呢,这是因为德丽莎很可爱!
// 没有力量的理想是戏言,没有理想的力量是空虚
#include <bits/stdc++.h>
#define LL long long
#define int long long
using namespace std;
char ibuf[1 << 15], *p1, *p2;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, 1 << 15, stdin), p1==p2) ? EOF : *p1++)
inline int read() {
char ch = getchar(); int x = 0, f = 1;
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return x * f;
}
void print(LL x) {
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
template<class T> bool chkmin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool chkmax(T &a, T b) { return a < b ? (a = b, true) : false; }
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define repd(i, l, r) for (int i = (l); i >= (r); i--)
#define REP(i, l, r) for (int i = (l); i < (r); i++)
const int N = 2e6, inf = 1e16;
int n, q, ans[N], H[N], a[N], b[N];
vector < pair<int,int> > Q[N], E[N];
int c[N], d[N], tag[N];
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }
void pushup(int p) { c[p] = max(c[ls(p)], c[rs(p)]); d[p] = max(d[ls(p)], d[rs(p)]); }
void build(int p,int l,int r) {
c[p] = d[p] = tag[p] = -inf;
if (l == r) return;
int mid = (l + r) >> 1;
build(ls(p), l, mid), build(rs(p), mid + 1, r);
}
void calc(int p,int val) {
tag[p] = max(tag[p], val);
d[p] = max(d[p], c[p] + tag[p]);
}
void pushdown(int p) {
if (tag[p] == -inf) return;
calc(ls(p), tag[p]); calc(rs(p), tag[p]); tag[p] = -inf;
}
void change(int p,int l,int r,int pos,int val) {
if (l == r) { c[p] = val; tag[p] = -inf; return; }
pushdown(p);
int mid = (l + r) >> 1;
if (pos <= mid) change(ls(p), l, mid, pos, val);
else change(rs(p), mid + 1, r, pos, val); pushup(p);
}
void update(int p,int l,int r,int nx,int ny,int val) {
if (nx <= l && r <= ny) { calc(p, val); return; }
pushdown(p);
int mid = (l + r) >> 1;
if (nx <= mid) update(ls(p), l, mid, nx, ny, val);
if (ny > mid) update(rs(p), mid + 1, r, nx, ny, val);
pushup(p);
}
int ask(int p,int l,int r,int nx,int ny) {
if (nx <= l && r <= ny) return d[p];
pushdown(p);
int mid = (l + r) >> 1, ans = -inf;
if (nx <= mid) ans = max(ans, ask(ls(p), l, mid, nx, ny));
if (ny > mid) ans = max(ans, ask(rs(p), mid + 1, r, nx, ny));
return ans;
}
void work() {
build(1, 1, n);
rep (i, 1, n) {
for (auto p : E[i]) change(1, 1, n, p.first, p.second ? H[p.first] : -inf);
if (i > a[i]) update(1, 1, n, max(i - b[i], 1ll), i - a[i], -H[i]);
for (auto it : Q[i]) ans[it.first] = max(ans[it.first], ask(1, 1, n, it.second, i));
}
}
void solve() {
n = read();
rep (i, 1, n) H[i] = read(), a[i] = read(), b[i] = read();
rep (i, 1, n) {
if (i + a[i] <= n) {
E[i + a[i]].push_back({i, 1});
if (i + b[i] + 1 <= n) E[i + b[i] + 1].push_back({i, 0});
}
}
q = read();
rep (i, 1, q) {
int l = read(), r = read();
Q[r].push_back({i, l});
ans[i] = -1;
}
work();
rep (i, 1, n) H[i] = 1e9 - H[i];
work();
rep (i, 1, q) printf("%lld\n", ans[i]);
}
signed main () {
#ifdef LOCAL_DEFINE
freopen("1.in", "r", stdin);
freopen("1.ans", "w", stdout);
#endif
int T = 1; while (T--) solve();
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}