[NOI2018] 归程 Solution

闲话

实在懒得写了。

Kruskal 重构树的思想理解难度过高,不如可持久化并查集,思路直接,代码好写,往机位上一坐,双手放在键盘上,直接不看键盘打,半个小时就写完了,还压根不需要调试。

如果要调试,只可能是数组开小了或者 memset 初始位置写错了。

代码

#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <functional>
#include <queue>
#include <utility>
#include <vector>
using namespace std;
const int N = 2e5 + 10, M = 4e5 + 10;
template <typename _Tp> inline void read(_Tp &x)
{
    char ch;
    while (ch = getchar(), !isdigit(ch) and ~ch)
        ;
    x = (ch ^ 48);
    while (ch = getchar(), isdigit(ch))
        x = (x << 3) + (x << 1) + (ch ^ 48);
}
template <typename _Tp, typename... _Args> inline void read(_Tp &x, _Args &...args)
{
    read(x);
    read(args...);
}
template <typename _Tp> inline void print(_Tp x)
{
    if (x > 9)
        print(x / 10);
    putchar((x % 10) ^ 48);
}
template <typename _Tp, typename... _Args> inline void print(_Tp x, _Args... args)
{
    print(x);
    putchar(' ');
    print(args...);
}
int n, m, idx1, idx2, rt[M];
using ll = long long;
ll dis[N];
bool vis[N];
using pli = pair<ll, int>;
using pii = pair<int, int>;
vector<pii> road[N];
struct node
{
    int ls, rs;
} tr[N << 6];
struct node2
{
    int fa, siz;
    ll res;
} trs[N << 2];
struct edge
{
    int x, y, l, a;
    bool operator<(const edge &ele) const
    {
        if (a != ele.a)
            return a > ele.a;
        if (l != ele.a)
            return l < ele.l;
        if (x != ele.x)
            return x < ele.x;
        return y < ele.y;
    }
} path[M];
priority_queue<pli, vector<pli>, greater<>> q;
void build(int &x, int l, int r)
{
    x = ++idx1;
    if (l == r)
    {
        tr[x].ls = ++idx2;
        trs[idx2] = {l, 1, dis[l]};
        return;
    }
    int mid = (l + r) >> 1;
    build(tr[x].ls, l, mid);
    build(tr[x].rs, mid + 1, r);
}
node2 query(int &x, int l, int r, int tar)
{
    if (l == r)
        return trs[tr[x].ls];
    int mid = (l + r) >> 1;
    if (tar <= mid)
        return query(tr[x].ls, l, mid, tar);
    return query(tr[x].rs, mid + 1, r, tar);
}
node2 buf;
void update(int &x, int l, int r, int tar)
{
    tr[++idx1] = tr[x];
    x = idx1;
    if (l == r)
    {
        tr[x].ls = ++idx2;
        trs[idx2] = buf;
        return;
    }
    int mid = (l + r) >> 1;
    if (tar <= mid)
        return update(tr[x].ls, l, mid, tar);
    return update(tr[x].rs, mid + 1, r, tar);
}
node2 find(int k, int x)
{
    int tmpr = 0;
    node2 tmp = query(rt[k], 1, n, x);
    while (tmp.fa != x)
    {
        x = tmp.fa;
        tmp = query(rt[k], 1, n, x);
        tmpr++;
    }
    return tmp;
}
void merge(int k, int x, int y)
{
    node2 tx = find(k, x), ty = find(k, y);
    if (tx.fa == ty.fa)
        return;
    if (tx.siz > ty.siz)
    {
        buf = ty;
        buf.fa = tx.fa;
        update(rt[k], 1, n, ty.fa);
        buf = {tx.fa, tx.siz + ty.siz, min(tx.res, ty.res)};
        update(rt[k], 1, n, tx.fa);
    }
    else
    {
        buf = tx;
        buf.fa = ty.fa;
        update(rt[k], 1, n, tx.fa);
        buf = {ty.fa, tx.siz + ty.siz, min(tx.res, ty.res)};
        update(rt[k], 1, n, ty.fa);
    }
}
int qr, k, s;
void init_global()
{
}
void init_local()
{
    read(n, m);
    idx1 = idx2 = 0;
    for (int i = 1; i <= n; i++)
        road[i].clear();
    for (int i = 1, x, y, l, a; i <= m; i++)
    {
        read(x, y, l, a);
        path[i] = {x, y, l, a};
        road[x].emplace_back(y, l);
        road[y].emplace_back(x, l);
    }
}
void run()
{
    memset(vis + 1, 0, n);
    memset(dis + 1, 0x3f, n << 3);
    q.emplace(0, 1);
    dis[1] = 0;
    while (q.size())
    {
        auto [cv, tx] = q.top();
        q.pop();
        if (vis[tx])
            continue;
        vis[tx] = true;
        for (auto &[i, v] : road[tx])
        {
            if (dis[i] <= cv + v or vis[i])
                continue;
            dis[i] = cv + v;
            q.emplace(cv + v, i);
        }
    }
    rt[0] = 0;
    build(rt[0], 1, n);
    sort(path + 1, path + m + 1);
    for (int i = 1; i <= m; i++)
    {
        rt[i] = rt[i - 1];
        merge(i, path[i].x, path[i].y);
    }
    read(qr, k, s);
    for (int i = 1, v, p, la = 0, tp; i <= qr; i++)
    {
        read(v, p);
        v = (v + k * la - 1) % n + 1;
        p = (p + k * la) % (s + 1);
        tp = lower_bound(path + 1, path + m + 1, edge{0, 0, 0, p}) - path - 1;
        la = find(tp, v).res;
        print(la);
        putchar('\n');
    }
}
int main()
{
    // freopen("return.in", "r", stdin);
    // freopen("return.out", "w", stdout);
    int T = 1;
    scanf("%d", &T);
    init_global();
    while (T--)
    {
        init_local();
        run();
    }
}
posted @ 2024-10-22 21:31  丝羽绫华  阅读(1)  评论(0编辑  收藏  举报