当前位置: 首页 > 工具软件 > CodeRally > 使用案例 >

AT1998 [AGC002D] Stamp Rally

郭阳曜
2023-12-01

https://www.luogu.com.cn/problem/AT1998

整体二分板子题

考虑二分编号,然后用并查集维护大小,注意并查集要支持撤回,用按秩合并并查集即可

时间复杂度 O ( n l o g 2 n ) O(n log^2n) O(nlog2n)

可以把dfs换成bfs,即把二分的建成一棵树,一层层处理,这样并查集就不用支持可撤回了,时间复杂度降到 O ( n l o g n ) O(nlogn) O(nlogn)

只写了第一种,第二种后面再补
code:

#include<bits/stdc++.h>
#define N 200050
using namespace std;
int fa[N], siz[N], top, ans[N];
pair<int, int> sta[N];
struct Q {
    int x, y, z, id;
} q[N], a[N], b[N];
struct E {
    int u, v;
} e[N];
int get(int x) {
    return fa[x] == x? x : get(fa[x]);
}
void merge(int x, int y) {
    x = get(x), y = get(y);
    if(x == y) return;
    if(siz[x] > siz[y]) swap(x, y);
    sta[++ top] = make_pair(x, y);
    fa[x] = y, siz[y] += siz[x];
}
void solve(int l, int r, int L, int R) { 
    // printf("%d %d %d %d\n", l, r, L, R);
    // for(int i = L; i <= R; i ++) printf(" %d ", q[i].id); printf("\n");
    if(l == r) {
        for(int i = L; i <= R; i ++) ans[q[i].id] = l;
        int x = get(e[l].u), y = get(e[l].v);
        if(x == y) return ;
        if(siz[x] > siz[y]) swap(x, y);
        fa[x] = y, siz[y] += siz[x];
        return ;
    }
    int mid = (l + r) >> 1;
    for(int i = l; i <= mid; i ++) merge(e[i].u, e[i].v);
    int gs = 0, gss = 0;
    for(int i = L; i <= R; i ++) {
        int x = get(q[i].x), y = get(q[i].y), s = 0;
        if(x == y) s = siz[x];
        else s = siz[x] + siz[y];
        if(s >= q[i].z) a[++ gs] = q[i];
        else b[++ gss] = q[i];
    }
    while(top) {
        int x = sta[top].first, y = sta[top].second; top --;
        fa[x] = x; siz[y] -= siz[x];
    }
    for(int i = 1; i <= gs; i ++) q[L + i - 1] = a[i];
    for(int i = 1; i <= gss; i ++) q[L + gs + i - 1] = b[i];
    solve(l, mid, L, L + gs - 1), solve(mid + 1, r, L + gs, R);
}
int n, m, qq;
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) fa[i] = i, siz[i] = 1;
    for(int i = 1; i <= m; i ++) scanf("%d%d", &e[i].u, &e[i].v);
    scanf("%d", &qq);
    for(int i = 1; i <= qq; i ++) scanf("%d%d%d", &q[i].x, &q[i].y, &q[i].z), q[i].id = i;
    solve(1, m, 1, qq);
    for(int i = 1; i <= qq; i ++) printf("%d\n", ans[i]);
    return 0;
}
 类似资料:

相关阅读

相关文章

相关问答