[题目链接] (https://codeforc.es/contest/500/problem/E)
题解:维护每个木棒能够覆盖的区间。
注意:因为要考虑一种情况就是前面的木棒如果将后面的位置都覆盖,那么结果就不正确了,所以要从后往前一边更新一边求答案。还有就是为什么更新时右端点要减一,举个例子,如果一根木棒在位置7,高度为1,一根木棒在位置9,高度为2。如果不减一,那么你会更新7,8,9,你会发现代价为0,而实际上代价为1,所以减一就是防止这种情况。
#include<bits/stdc++.h>
#define mid (l + r) / 2
using namespace std;
const int maxn = 2e5 + 10, N = 1e9;
int ls[maxn * 31], rs[maxn * 31], sum[maxn * 31], tag[maxn * 31], cnt;
int p[maxn], h[maxn], x[maxn], y[maxn], ans[maxn];
vector<int> G[maxn];
void pushdown(int o, int l, int r)
{
if (tag[o]) {
if (!ls[o])
ls[o] = ++cnt;
if (!rs[o])
rs[o] = ++cnt;
tag[ls[o]] = tag[rs[o]] = 1;
sum[ls[o]] = mid - l + 1;
sum[rs[o]] = r - mid;
tag[o] = 0;
}
}
void up(int &o, int l, int r, int ql, int qr)
{
if (sum[o] == r - l + 1)
return;
if (!o)
o = ++cnt;
if (l >= ql && r <= qr) {
tag[o] = 1;
sum[o] = r - l + 1;
return;
}
if(ql>mid) up(rs[o],mid+1,r,ql,qr);
else if(qr<=mid) up(ls[o],l,mid,ql,qr);
else {
up(ls[o],l,mid,ql,qr);
up(rs[o],mid+1,r,ql,qr);
}
sum[o] = sum[ls[o]] + sum[rs[o]] ;
}
int qu(int o, int l, int r, int ql, int qr)
{
if (l >= ql && r <= qr)
return sum[o];
pushdown(o, l, r);
int cat = 0;
if (ql <= mid)
cat += qu(ls[o], l, mid, ql, qr);
if (qr > mid)
cat += qu(rs[o], mid + 1, r, ql, qr);
return cat ;
}
int main() {
int n, q, rt = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &p[i], &h[i]);
scanf("%d", &q);
for (int i = 1; i <= q; i++) {
scanf("%d%d", &x[i], &y[i]);
G[x[i]].push_back(i);
}
for (int i = n; i; i--) {
up(rt, 1, N, p[i], min(N, p[i] + h[i] - 1));
for (auto id : G[i])
ans[id] = p[y[id]] - p[x[id]] - qu(rt, 1, N, p[x[id]], p[y[id]] - 1);
}
for (int i = 1; i <= q; i++)
printf("%d\n", ans[i]);
}