D. Colored Portals

题面

分析

如果 x x x y y y 能够直接到达,那么最近的一定是二者绝对值,如果不能直接到达,需要找一个中间量,那么最优方法就是找一个新的 z z z ,有以下三种情况:

  • 如果 z < x z \lt x z<x ,那么最短距离为 ( x − z ) + ( y − z ) (x - z) + (y - z) (xz)+(yz)
  • 如果 x ≤ z ≤ y x \leq z \leq y xzy ,那么最短距离为 ( y − x ) (y - x) (yx)
  • 如果 z > y z \gt y z>y ,那么最短距离为 ( z − x ) + ( z − y ) (z - x) + (z - y) (zx)+(zy)
    可以发现从 x x x 出发那么最优方案就是选一个距离 x x x 最短的点作为中间量。
代码
#include <bits/stdc++.h>

using namespace std;
using ll = long long;

string c[] = {"BG", "BR", "BY", "GR", "GY", "RY"};

void solve() {
    int n, q;
    cin >> n >> q;
    vector<int> a(n);
    vector<vector<int>> l(n, vector<int>(6));
    vector<vector<int>> r(n, vector<int>(6));
    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < 6; ++j) {
            if (s == c[j]) {
                a[i] = j;
                break;
            }
        }
    }
    for (int i = 0; i < 6; ++i) {
        int last = 1e9;
        for (int j = 0; j < n; ++j) {
            l[j][i] = last;
            if (a[j] == i) {
                last = j;
            }
        }
        last = 1e9;
        for (int j = n - 1; j >= 0; --j) {
            r[j][i] = last;
            if (a[j] == i) {
                last = j;
            }
        }
    }
    while (q--) {
        int x, y;
        cin >> x >> y;
        --x, --y;
        int ans = 1e9;
        for (int i = 0; i < 6; ++i) {
            string s = c[i];
            string s1 = c[a[x]];
            string s2 = c[a[y]];
            if (s1 == s2) {
                ans = min(ans, abs(x - y));
            }
            if ((s1[0] == s[0] || s1[0] == s[1] || s1[1] == s[0] || s1[1] == s[1]) && (s2[0] == s[0] || s2[0] == s[1] || s2[1] == s[0] || s2[1] == s[1])) {
                ans = min(ans, abs(x - l[x][i]) + abs(y - l[x][i]));
                ans = min(ans, abs(x - r[x][i]) + abs(y - r[x][i]));
            }
        }
        if (ans == 1e9) ans = -1;
        cout << ans << "\n";
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;
    while (T--) {
        solve();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值