Farmer John最讨厌的农活是运输牛粪。为了精简这个过程,他产生了一个新奇的想法:与其使用拖拉机拖着装满牛粪的大车从一个地点到另一个地点,为什么不用一个巨大的便便弹弓把牛粪直接发射过去呢?(事实上,好像哪里不太对……) Farmer John的农场沿着一条长直道路而建,所以他农场上的每个地点都可以简单地用该地点在道路上的位置来表示(相当于数轴上的一个点)。FJ建造了\(N\)个弹弓(\(1 \leq N \leq 10^5\)),其中第\(i\)个弹弓可以用三个整数\(x_i\),\(y_i\)以及\(t_i\)描述,表示这个弹弓可以在\(t_i\)单位时间内将牛粪从位置\(x_i\)发射到位置\(y_i\)。
FJ有\(M\)堆牛粪需要运输(\(1 \leq M \leq 10^5\))。第\(j\)堆牛粪需要从位置\(a_j\)移动到位置\(b_j\)。使用拖拉机运输牛粪,经过路程\(d\)需要消耗\(d\)单位时间。FJ希望通过对每一堆牛粪使用至多一次弹弓来减少运输时间。FJ驾驶没有装载牛粪的拖拉机的时间不计。
对这\(M\)堆牛粪的每一堆,在FJ可以在运输过程中使用至多一次弹弓的条件下,帮助FJ求出其最小运输时间。
输入的第一行包含\(N\)和\(M\)。下面\(N\)行,每行用\(x_i\),\(y_i\),\(t_i\)(\(0 \leq x_i, y_i, t_i \leq 10^9\))描述了一个弹弓。最后\(M\)行用\(a_j\)和\(b_j\)描述了需要移动的牛粪。
输出\(M\)行,每堆牛粪一行,表示运输这堆牛粪需要的最短时间。
2 3
0 10 1
13 8 2
1 12
5 2
20 7
4
3
10
none
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const LL inf = 999999999999999LL;
const int maxn = 6e5 + 100;
struct Tree {
protected:
struct node {
node *ch[2];
int l, r;
LL min;
node(int l = 0, int r = 0, LL min = inf): l(l), r(r), min(min) {}
void *operator new(size_t) {
static node *S = NULL, *T = NULL;
return (S == T) && (T = (S = new node[1024]) + 1024), S++;
}
void upd() { min = std::min(ch[0]->min, ch[1]->min); }
};
node *root;
void build(node *&o, int l, int r) {
o = new node(l, r, inf);
if(l == r) return;
int mid = (l + r) >> 1;
build(o->ch[0], l, mid), build(o->ch[1], mid + 1, r);
}
void lazy(node *o, int p, LL k) {
if(o->r < p || o->l > p) return;
if(o->l == o->r) return (void)(o->min = std::min(o->min, k));
lazy(o->ch[0], p, k), lazy(o->ch[1], p, k);
o->upd();
}
LL query(node *o, int l, int r) {
if(o->r < l || o->l > r) return inf;
if(l <= o->l && o->r <= r) return o->min;
return std::min(query(o->ch[0], l, r), query(o->ch[1], l, r));
}
void clr(node *o) {
o->min = inf;
if(o->l == o->r) return;
clr(o->ch[0]), clr(o->ch[1]);
}
public:
void build(int n) { build(root, 1, n); }
void lazy(int p, LL k) { lazy(root, p, k); }
LL query(int l, int r) { return query(root, l, r); }
void clr() { clr(root); }
}s;
struct Q {
int x, y;
LL val;
Q(int x = 0, int y = 0, LL val = 0): x(x), y(y), val(val) {}
friend bool operator < (const Q &a, const Q &b) {
return a.y == b.y? a.x < b.x : a.y < b.y;
}
}q[maxn], d[maxn];
int n, m;
LL a[maxn];
LL ans[maxn];
int main() {
n = in(), m = in();
int x, y, t, len = 0;
for(int i = 1; i <= n; i++) {
x = in(), y = in(), t = in();
d[i] = Q(x, y, t);
a[++len] = x, a[++len] = y;
}
for(int i = 1; i <= m; i++) {
x = in(), y = in();
q[i] = Q(x, y, i);
a[++len] = x, a[++len] = y;
ans[i] = y > x? y - x : x - y;
}
std::sort(a + 1, a + len + 1);
int _ = 1;
for(int i = 2; i <= len; i++) if(a[i] != a[i - 1]) a[++_] = a[i];
len = _;
s.build(len);
for(int i = 1; i <= n; i++) {
d[i].x = std::lower_bound(a + 1, a + len + 1, d[i].x) - a;
d[i].y = std::lower_bound(a + 1, a + len + 1, d[i].y) - a;
}
for(int i = 1; i <= m; i++) {
q[i].x = std::lower_bound(a + 1, a + len + 1, q[i].x) - a;
q[i].y = std::lower_bound(a + 1, a + len + 1, q[i].y) - a;
}
std::sort(d + 1, d + n + 1);
std::sort(q + 1, q + m + 1);
int now = 1;
for(int i = 1; i <= m; i++) {
while(now <= n && d[now].y <= q[i].y) {
s.lazy(d[now].x, - a[d[now].x] - a[d[now].y] + d[now].val);
now++;
}
ans[q[i].val] = std::min(ans[q[i].val], a[q[i].x] + a[q[i].y] + s.query(1, q[i].x));
}
now = 1, s.clr();
for(int i = 1; i <= m; i++) {
while(now <= n && d[now].y <= q[i].y) {
s.lazy(d[now].x, a[d[now].x] - a[d[now].y] + d[now].val);
now++;
}
ans[q[i].val] = std::min(ans[q[i].val], - a[q[i].x] + a[q[i].y] + s.query(q[i].x, len));
}
now = n, s.clr();
for(int i = m; i >= 1; i--) {
while(now >= 1 && d[now].y >= q[i].y) {
s.lazy(d[now].x, - a[d[now].x] + a[d[now].y] + d[now].val);
now--;
}
ans[q[i].val] = std::min(ans[q[i].val], a[q[i].x] - a[q[i].y] + s.query(1, q[i].x));
}
now = n, s.clr();
for(int i = m; i >= 1; i--) {
while(now >= 1 && d[now].y >= q[i].y) {
s.lazy(d[now].x, a[d[now].x] + a[d[now].y] + d[now].val);
now--;
}
ans[q[i].val] = std::min(ans[q[i].val], - a[q[i].x] - a[q[i].y] + s.query(q[i].x, len));
}
for(int i = 1; i <= m; i++) printf("%lld\n", ans[i]);
return 0;
}
P4088 [USACO18FEB]Slingshot 线段树+扫描线
原文:https://www.cnblogs.com/olinr/p/10357886.html