题解:P16679 [CSPro 27] 吉祥物投票

· · 题解

什么缝合怪题。

:::success[Code]{open}


#include <iostream>
#include <set>
using namespace std;

#define MAXN 200005

int n, m, q;

struct Seg
{
    int l, r, v;
    friend bool operator<(const Seg &l, const Seg &r)
    {
        return l.r < r.r;
    }
};
set<Seg> odt;
int sid = 0;

int cnt[MAXN];
struct SegTree
{
    int t[MAXN << 2];
    #define ls (p << 1)
    #define rs (p << 1 | 1)

    void pushup(int p)
    {
        if (cnt[t[ls]] >= cnt[t[rs]])
        {
            t[p] = t[ls];
        }
        else
        {
            t[p] = t[rs];
        }
    }

    void build(int p, int l, int r)
    {
        if (l == r)
        {
            t[p] = l;
            return;
        }
        int mid = (l + r) >> 1;
        build(ls, l, mid);
        build(rs, mid + 1, r);
        pushup(p);
    }

    void upd(int p, int l, int r, int q)
    {
        if (l == r || !q)
        {
            return;
        }
        int mid = (l + r) >> 1;
        if (mid >= q)
        {
            upd(ls, l, mid, q);
        }
        else
        {
            upd(rs, mid + 1, r, q);
        }
        pushup(p);
    }
} seg;

struct DSU
{
    int fa[MAXN << 2];
    int sz[MAXN << 2];

    int find(int x)
    {
        return x == fa[x] ? x : fa[x] = find(fa[x]);
    }

    void mergets(int u, int v)
    {
        u = find(u), v = find(v);
        if (u == v)
        {
            return;
        }
        fa[v] = u;
        sz[u] += sz[v];
    }

    int unlink(int u)
    {
        int f = find(u);
        sz[f] -= sz[u];
        fa[u] = u;
        return f;
    }
} dsu;

int dir[MAXN], rid[MAXN << 2];

void upd(int f)
{
    cnt[rid[f]] = dsu.sz[f];
    seg.upd(1, 1, m, rid[f]);
}

set<Seg>::iterator split(int p)
{
    if (!p)
    {
        return odt.begin();
    }
    auto it = odt.lower_bound(Seg{0, p, 0});
    if (it->r == p)
    {
        return next(it);
    }
    auto [l, r, v] = *it;
    odt.erase(it);
    int f = dsu.unlink(v);
    dsu.sz[v] = (p - l + 1);
    dsu.mergets(f, v);
    ++sid;
    dsu.fa[sid] = sid;
    dsu.sz[sid] = (r - p);
    dsu.mergets(f, sid);
    upd(f);
    odt.insert(Seg{l, p, v});
    return odt.insert(Seg{p + 1, r, sid}).first;
}

void segfill()
{
    int l, r, w;
    cin >> l >> r >> w;
    auto itr = split(r), itl = split(l - 1);
    for (auto it = itl; it != itr; ++it)
    {
        upd(dsu.unlink(it->v));
    }
    odt.erase(itl, itr);
    ++sid;
    dsu.fa[sid] = sid;
    dsu.sz[sid] = r - l + 1;
    dsu.mergets(dir[w], sid);
    upd(dir[w]);
    odt.insert(Seg{l, r, sid});
}

void redir()
{
    int u, v;
    cin >> u >> v;
    cnt[v] += cnt[u];
    cnt[u] = 0;
    dsu.mergets(dir[v], dir[u]);
    dir[u] = ++sid;
    rid[sid] = u;
    dsu.fa[sid] = sid;
    seg.upd(1, 1, m, u), seg.upd(1, 1, m, v);
}

void swp()
{
    int u, v;
    cin >> u >> v;
    swap(cnt[u], cnt[v]);
    swap(dir[u], dir[v]);
    swap(rid[dir[u]], rid[dir[v]]);
    seg.upd(1, 1, m, u), seg.upd(1, 1, m, v);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m >> q;
    seg.build(1, 1, m);
    cnt[0] = n;
    odt.insert({1, n, 0});
    sid = m + 1;
    dir[0] = m + 1;
    dsu.sz[0] = n;
    for (int i = 1; i <= m; i++)
    {
        dsu.fa[i] = i;
        dir[i] = i;
        rid[i] = i;
    }
    dsu.fa[m + 1] = m + 1;
    dsu.mergets(m + 1, 0);
    while (q--)
    {
        int o;
        cin >> o;
        if (o == 1)
        {
            segfill();
        }
        else if (o == 2)
        {
            redir();
        }
        else if (o == 3)
        {
            swp();
        }
        else if (o == 4)
        {
            int w;
            cin >> w;
            cout << cnt[w] << '\n';
        }
        else
        {
            int w = seg.t[1];
            cout << !!cnt[w] * w << '\n';
        }
    }
    return 0;
}

:::