CodeForces-1691E Number of Groups

Number of Groups#

并查集 + set

我觉得这个题 cf 自己的题解写的挺好的

把所有的区间段化成左端点和右端点的方式,然后从左到右逐个遍历点,这样就可以降维

如果当前访问到一个左端点,则加入到 set 当中,表示现在是处于这个区间段上的,当然当前的点可以处于多个区间段内

如果当前访问到一个右端点,就直接删除掉 set 中,这个段的左端点,表示现在已经不在这个区间段内了

在访问左端点的时候,当前线段显然于存在 set 中的所有线段有交点,这样就可以直接开始用并查集维护了

如果都是重合到一起,显然操作还是 O(n2)

其实我们只需要留下一个能合并的区间中,右端点最远的作为这个集合的代表,提供给后面的线段进行合并,其他的都是可以删掉的,这样建图就能保证是在 O(n) 的了

然后有两种颜色,所以要用两个 set 去分别维护两种颜色,操作都和上述的表示一致

复杂度为 O(nlogn)

#include <iostream>
#include <cstdio>
#include <set>
#include <map>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define pii pair<int, int>
const int maxn = 1e5 + 10;
int top[maxn], vis[maxn << 1];

struct node
{
    int t, l, r, id;
}seg[maxn];

int query(int x)
{
    return x == top[x] ? x : top[x] = query(top[x]);
}

inline void comb(int x, int y)
{
    int fx = query(x);
    int fy = query(y);
    if(fx != fy)
        top[fx] = fy;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while(t--)
    {
        int n;
        cin >> n;
        map<int, vector<pii>>mp;
        for(int i=0; i<=n; i++) top[i] = i;
        for(int i=1; i<=n; i++)
        {
            int t, l, r;
            cin >> t >> l >> r;
            seg[i] = {t, l, r, i};
            mp[l].push_back({0, i});
            mp[r].push_back({1, i});
        }
        set<int>s[2];
        for(auto it=mp.begin(); it!=mp.end(); it++)
        {
            sort(it->second.begin(), it->second.end());
            for(int i=0; i<it->second.size(); i++)
            {
                pii now = it->second[i];
                node p = seg[now.second];
                if(now.first == 0)
                {
                    if(s[p.t ^ 1].size())
                    {
                        int way = -1, nex = 0;
                        for(auto j=s[p.t ^ 1].begin(); j!=s[p.t ^ 1].end(); j++)
                        {
                            comb(*j, now.second);
                            vis[*j] = 0;
                            if(seg[*j].r > way)
                            {
                                way = seg[*j].r;
                                nex = *j;
                            }
                        }
                        s[p.t ^ 1].clear();
                        s[p.t ^ 1].insert(nex);
                        vis[nex] = 1;
                    }
                    s[p.t].insert(p.id);
                    vis[p.id] = 1;
                }
                else
                {
                    if(vis[now.second])
                    {
                        vis[now.second] = 0;
                        s[p.t].erase(p.id);
                    }
                }
            }
        }
        int ans = 0;
        for(int i=1; i<=n; i++) ans += top[i] == i;
        cout << ans << endl;
    }
    return 0;
}
posted @   dgsvygd  阅读(76)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
主题色彩