P10137

· · 题解

来个神 Eterna 的不用倍增的做法。但是和倍增做法本质相同。

考虑会改变方向的情况,就是当前点到交叉路口的长度是奇数。

将所有长度为偶数的边删去,新建一个图,则答案形如:

代码实现细节还是有点多,不过 Eterna 认为非常的好写。

时间复杂度 \mathcal{O}((n+q)\log n),空间复杂度 \mathcal{O}(n)。 ::::success[code]

#include <bits/stdc++.h>
#define int long long
#define rd read()
using namespace std;
inline int read() {
    int x = 0; char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    return x;
}
const int N = 2e5 + 5, inf = 1e18;
int n, q;
vector<int> px, Px, py, Py;
map<int, int> vx, vy;
signed main() {
    n = rd, q = rd;
    for (int i = 1; i <= n; ++i) {
        char c; cin >> c; int v = rd;
        if (c == 'H') py.push_back(v), vy[v] = 1;
        else px.push_back(v), vx[v] = 1;
    }
    sort(px.begin(), px.end()); sort(py.begin(), py.end());
    if (px.size()) {
        Px.push_back(px[0]);
        for (int i = 1; i < px.size(); ++i) 
            if ((px[i] - px[i - 1]) & 1) Px.push_back(px[i]);
    }
    if (py.size()) {
        Py.push_back(py[0]);
        for (int i = 1; i < py.size(); ++i) 
            if ((py[i] - py[i - 1]) & 1) Py.push_back(py[i]);
    }
    px.push_back(inf), py.push_back(inf), Px.push_back(inf), Py.push_back(inf);
    for (int i = 1, d, x, y; i <= q; ++i) {
        x = rd, y = rd, d = rd;
        int t = 0, f = 0,
        X = upper_bound(px.begin(), px.end(), x) - px.begin(),
        Y = upper_bound(py.begin(), py.end(), y) - py.begin();
        if (vx[x]) {
            if (py[Y] - y >= d) {cout << x << ' ' << y + d << '\n'; f = 1;}
            else d -= py[Y] - y, t += py[Y] - y, y = py[Y];
        } else {
            if (px[X] - x >= d) {cout << x + d << ' ' << y << '\n'; f = 1;}
            else d -= px[X] - x, t += px[X] - x, x = px[X];
        }
        if (!f) {
            X = upper_bound(Px.begin(), Px.end(), x) - Px.begin();
            Y = upper_bound(Py.begin(), Py.end(), y) - Py.begin();
            if (t & 1) {
                if (Px[X] - x >= d) {cout << x + d << ' ' << y << '\n'; f = 1;}
                else {
                    d -= Px[X] - x, t += Px[X] - x, x = Px[X];
                    if (Py[Y] - y >= d) {cout << x << ' ' << y + d << '\n'; f = 1;}
                    else d -= Py[Y] - y, t += Py[Y] - y, y = Py[Y];
                }
            } else {
                if (Py[Y] - y >= d) {cout << x << ' ' << y + d << '\n'; f = 1;}
                else {
                    d -= Py[Y] - y, t += Py[Y] - y, y = Py[Y];
                    if (Px[X] - x >= d) {cout << x + d << ' ' << y << '\n'; f = 1;}
                    else d -= Px[X] - x, t += Px[X] - x, x = Px[X];
                }
            }
            int l = 1, r = min(Px.size() - X, Py.size() - Y) - 1, res = 0;
            while (l <= r) {
                int mid = l + r >> 1;
                if (Px[X + mid] - Px[X] + Py[Y + mid] - Py[Y] <= d) l = mid + 1, res = mid;
                else r = mid - 1;
            }
            d -= Px[X + res] - Px[X] + Py[Y + res] - Py[Y];
            t += Px[X + res] - Px[X] + Py[Y + res] - Py[Y];
            X += res, Y += res;
            while (!f) {
                if (t & 1) {
                    if (Px[X + 1] - Px[X] >= d) {cout << Px[X] + d << ' ' << Py[Y] << '\n'; f = 1;}
                    else d -= Px[X + 1] - Px[X], t += Px[X + 1] - Px[X], ++X;
                } else {
                    if (Py[Y + 1] - Py[Y] >= d) {cout << Px[X] << ' ' << Py[Y] + d << '\n'; f = 1;}
                    else d -= Py[Y + 1] - Py[Y], t += Py[Y + 1] - Py[Y], ++Y;
                }
            }
        }
    }
    return 0;
}