站外题求调CFGym100861D过样例MLEonTest1,玄2关
  • 板块题目总版
  • 楼主Infter
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/4/12 21:09
  • 上次更新2024/4/13 08:28:44
查看原帖
站外题求调CFGym100861D过样例MLEonTest1,玄2关
386547
Infter楼主2024/4/12 21:09

题目大意:给定一n边形的三角剖分,q次询问求两点最短路,最短指经过的边最短。

大体思路:分治,每次重新编号找最均匀的对角线切成两半,经过这条对角线的端点的利用该对角线计算,其他的分治下去。

Code

#include <bits/stdc++.h>
using namespace std;

constexpr int MAXN = 1e5 + 5;

int n;

int findrt(vector<pair<int, int>> Edge, int n) {
    int mx = 0, ans;
    for (int i = 0; i < Edge.size(); i++) {
        int u = Edge[i].first;
        int v = Edge[i].second;
        int now = abs(u - v);
        if (now > n / 2)
            now = n - now;
        if (now > mx) {
            mx = now;
            ans = i;
        }
    }
    return ans;
}

int num[MAXN][50], from[MAXN][50];
int temp[MAXN * 2];

struct Query {
    int x, y, ans;
    bool operator<(const Query& oth) const {
        return make_pair(make_pair(x, y), ans) < make_pair(make_pair(oth.x, oth.y), oth.ans);
    }
};

int renumber(vector<pair<int, int>>& Edge, vector<Query>& Ask, int dep) {
    int tot = 0;
    for (auto [u, v] : Edge) {
        temp[++tot] = u;
        temp[++tot] = v;
    }
    sort(temp + 1, temp + tot + 1);
    tot = unique(temp + 1, temp + tot + 1) - temp - 1;

    for (auto& [u, v] : Edge) {
        u = num[u][dep] = lower_bound(temp + 1, temp + tot + 1, u) - temp;
        v = num[v][dep] = lower_bound(temp + 1, temp + tot + 1, v) - temp;
        from[num[u][dep]][dep] = u;
        from[num[v][dep]][dep] = v;
    }
    for (auto& [u, v, ans] : Ask) {
        u = num[u][dep];
        v = num[v][dep];
    }
    return tot;
}

vector<vector<int>> build(vector<pair<int, int>> Edge, int n) {
    vector<vector<int>> G(n + 1);
    for (auto [u, v] : Edge) {
        G[u].push_back(v);
        G[v].push_back(u);
    }
    return G;
}

vector<int> bfs(int x, vector<vector<int>> G) {
    vector<int> dis(n + 1, -1);
    dis[x] = 0;
    queue<int> q;
    q.push(x);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int v : G[u]) {
            if (dis[v] == -1) {
                dis[v] = dis[u] + 1;
                q.push(v);
            }
        }
    }
    return dis;
}

bool chk(int l, int r, int x) {
    return l <= x && x <= r;
}

int chk2(int l, int r, int x) {
    if (x == l || x == r)
        return 0;
    if (chk(l, r, x))
        return 1;
    return -1;
}

void solve(vector<pair<int, int>> Edge, vector<Query>& Ask, int dep) {
    // for (int i = 0; i < dep; i++)
    //     cerr << "  ";
    // cerr << "> {";
    // for (auto [u, v] : Edge) {
    //     cerr << "{" << u << " " << v << "} ";
    // }
    // cerr << "} {";
    // for (auto [u, v, ans] : Ask) {
    //     cerr << "{" << u << " " << v << " " << ans << "} ";
    // }
    // cerr << "}" << endl;
    int n = renumber(Edge, Ask, dep);
    if (n == 3) {
        for (auto& [u, v, ans] : Ask) {
            if (u == v)
                ans = 0;
            else
                ans = 1;
        }
        return;
    }
    int rt = findrt(Edge, n);
    int x = Edge[rt].first;
    int y = Edge[rt].second;
    if (x > y)
        swap(x, y);
    vector<pair<int, int>> leftE, rightE;
    vector<Query> leftQ, rightQ;

    vector<vector<int>> G = build(Edge, n);

    vector<int> dis1 = bfs(x, G);
    vector<int> dis2 = bfs(y, G);

    map<pair<int, int>, int> mp;

    for (auto& [u, v, ans] : Ask) {
        if (u == x)
            ans = dis1[v];
        else if (u == y)
            ans = dis2[v];
        else if (v == x)
            ans = dis1[u];
        else if (v == y)
            ans = dis2[u];
        else if (chk(x, y, u) ^ chk(x, y, v)) {
            ans = min(dis1[u] + dis1[v], dis2[u] + dis2[v]);
        } else if (chk(x, y, u)) {
            leftQ.push_back({ u, v, ans });
        } else {
            rightQ.push_back({ u, v, ans });
        }
    }

    for (auto [u, v] : Edge) {
        if (chk2(x, y, u) + chk2(x, y, v) >= 0) {
            leftE.push_back(make_pair(u, v));
        }
        if (chk2(x, y, u) + chk2(x, y, v) <= 0) {
            rightE.push_back(make_pair(u, v));
        }
    }
    solve(leftE, leftQ, dep + 1);
    solve(rightE, rightQ, dep + 1);
    for (auto [u, v, ans] : leftQ)
        mp[make_pair(u, v)] = ans;
    for (auto [u, v, ans] : rightQ)
        mp[make_pair(u, v)] = ans;
    for (auto& [u, v, ans] : Ask)
        if (!ans && u != v)
            ans = mp[make_pair(u, v)];

    for (auto& [u, v, ans] : Ask) {
        u = from[u][dep];
        v = from[v][dep];
    }

    // for (int i = 0; i < dep; i++)
    //     cerr << "  ";
    // cerr << "< {";
    // for (auto [u, v] : Edge) {
    //     cerr << "{" << u << " " << v << "} ";
    // }
    // cerr << "} {";
    // for (auto [u, v, ans] : Ask) {
    //     cerr << "{" << u << " " << v << " " << ans << "} ";
    // }
    // cerr << "}" << endl;
}

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

    cin >> n;
    vector<pair<int, int>> Edge;
    for (int i = 1; i <= n - 3; i++) {
        int x, y;
        cin >> x >> y;
        Edge.push_back(make_pair(x, y));
    }
    for (int i = 1; i < n; i++) {
        Edge.push_back(make_pair(i, i + 1));
    }
    Edge.push_back(make_pair(1, n));
    int q;
    cin >> q;
    vector<Query> Ask;
    for (int i = 1; i <= q; i++) {
        int x, y;
        cin >> x >> y;
        Ask.push_back({ x, y, 0 });
    }
    solve(Edge, Ask, 0);

    for (auto [u, v, ans] : Ask) {
        cout << ans << endl;
    }

    return 0;
}
2024/4/12 21:09
加载中...