首页 > 其他分享 >AGC002D Stamp Rally 多种做法 kruskal重构树/可持久化并查集/整体二分

AGC002D Stamp Rally 多种做法 kruskal重构树/可持久化并查集/整体二分

时间:2023-04-14 21:59:55浏览次数:50  
标签:sz Stamp kruskal 查集 mid find int upd

D - Stamp Rally (atcoder.jp)

这题做法很多,我写的是可持久化并查集做法,但是裸的可持久化并查集是 $O(nlog^3n)$,能过但是很慢!看洛谷的题解有一位大佬写了一个很妙的并查集的写法,按秩合并,每一步合并时用vector记录一下这个被合并到的节点的size和当前的时间,这样做可以找到每一个时间每一个节点的集合的size,时间复杂度是 $O(nlog^2n)$,非常巧妙!

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

constexpr int N = 2e5 + 10;

int sz[N], f[N], tim[N];
int find(int x, int t) {
    while(t >= tim[x]) {
        x = f[x];
    }
    return x;
}
void solve() {
    int n, m;
    cin >> n >> m;
    vector<vector<pair<int, int>>> upd(n + 1);
    for(int i = 1; i <= n; i++) {
        f[i] = i, sz[i] = 1, tim[i] = m + 1, upd[i].push_back({0, 1});
    }
    for(int i = 1; i <= m; i++) {
        int u, v;
        cin >> u >> v;
        int x = find(u, i), y = find(v, i);
        if(x == y) continue;
        if(sz[x] < sz[y]) swap(x, y);
        tim[y] = i;
        f[y] = x;
        sz[x] += sz[y];
        upd[x].push_back({i, sz[x]});
    }
    int q;
    cin >> q;
    for(int i = 1; i <= q; i++) {
        int u, v, z;
        cin >> u >> v >> z;
        auto check = [&](int t) {
            int x = find(u, t), y = find(v, t);
            if(x == y) {
                auto it = --upper_bound(upd[x].begin(), upd[x].end(), make_pair(t, n + 1));
                return it -> second >= z;
            }
            else {
                auto it1 = --upper_bound(upd[x].begin(), upd[x].end(), make_pair(t, n + 1));
                auto it2 = --upper_bound(upd[y].begin(), upd[y].end(), make_pair(t, n + 1));
                return it1 -> second + it2 -> second >= z;
            }
        };
        int lo = 1, hi = m;
        while(lo < hi) {
            int mid = lo + hi >> 1;
            if(check(mid)) hi = mid;
            else lo = mid + 1;
        }
        cout << lo << '\n';
    }
    
}

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

    int t;
    t = 1;

    while(t--) {
        solve();
    }

    return 0;
}

 

标签:sz,Stamp,kruskal,查集,mid,find,int,upd
From: https://www.cnblogs.com/Leonard7/p/17320043.html

相关文章

  • HDU 1878 欧拉回路 (并查集+欧拉回路)
    题目地址:HDU1878这个题要注意欧拉回路与欧拉通路的区别。在都保证连通性的前提下,欧拉回路要求每个点的度数都是偶数,而欧拉通路允许两个点的度数是奇数。所以这题用并查集判断连通性后判断下度数就可以了。代码如下:#include<iostream>#include<string.h>#include<math.h>#in......
  • POJ 2337 Catenyms (欧拉回路+并查集)
    题目地址:POJ2337这题跟POJ1386差不多,只不过这题多一个输出路径而已。按字母来建边,每个单词的首字母和尾字母加边。先判断是否连通,然后判断每个字母的入度和出度不能出现差的绝对值大于2,然后入度和出度差的绝对值为1的不能超过两个。就可以形成欧拉路径代码如下:#include<iostream......
  • POJ 1182 食物链(种类并查集)
    题目地址:POJ1182一道很经典的种类并查集的题目。利用互相之间的关系来进行权值的维护。代码如下:#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<stdlib.h>#include<math.h>#include<ctype.h>#include<queue>#in......
  • POJ 1703 Find them, Catch them(种类并查集)
    题目地址:POJ1703种类并查集水题。代码如下:#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<stdlib.h>#include<math.h>#include<ctype.h>#include<queue>#include<map>#includ......
  • POJ 1988 Cube Stacking (种类并查集)
    题目地址:POJ1988   这道题的查找合并的方法都能想的到,就是一点没想到,我一直天真的以为查询的时候,输入后能马上输出,这样的话在合并的时候就要所有的结点值都要算出来,但是经过路径压缩之后,没办法全部都处理到,如果不压缩妥妥的TLE。。于是看了看网上的题解。才发现自己是多......
  • HDU 1856 More is better(并查集+离散化)
    题目地址:HDU1856水题。由于标号范围太大,而数据数只有10w,所以要先进行离散化。然后就是裸的并查集了。代码如下:#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<stdlib.h>#include<math.h>#include<ctype.h>#include<que......
  • HDU 2473 Junk-Mail Filter(并查集的删除操作)
    题目地址:HDU2473这题以前碰到过,没做出来。。现在又做了做,还是没做出来。。、、这题涉及到并查集的删除操作。想到了设一个虚节点,但是我把虚节点设为了要删除的点的父节点,一直是栈溢出,目测是无限递归了。看了看别人的做法,原来只要建一个映射就可以了,虚节点是作为的新的映射,每......
  • HDU 2120 Ice_cream's world I(并查集)
    题目地址:HDU2120这题虽然字数不多,但就是看不懂。。意思是求最多有多少个被墙围起来的区域。显然就是求环的个数。然后用并查集求环个数就可以了。代码如下:#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<stdlib.h>#include<math......
  • timestamp时间戳
    1.这个博客学习timestamp1.占用4个字节2.允许为空值,但是不可以自定义值,所以为空值时没有任何意义。3.TIMESTAMP值不能早于1970或晚于2037。这说明一个日期,例如'1968-01-01',虽然对于DATETIME或DATE值是有效的,但对于TIMESTAMP值却无效,如果分配给这样一个对象将被转换为0。4.值......
  • 如何将oracle.sql.TIMESTAMP 转换为 java date
    privateStringgetDate(Objectvalue){Timestamptimestamp=null;try{timestamp=(Timestamp)value;}catch(Exceptione){timestamp=getOracleTimestamp(value);}if(timestamp!=null)return(newSimpleDateFormat("yyyy-MM-ddHH:mm:ss.S&......