首页 > 其他分享 >Codeforces 1278D 题解

Codeforces 1278D 题解

时间:2023-10-01 19:34:10浏览次数:50  
标签:int 题解 make Codeforces 1278D fa tg find

题目大意

题目大意

给你 \(n\) ( \(1\leqslant n\leqslant 5\cdot 10^5\) ) 条线段 \([l_1, r_1], [l_2, r_2], \cdots, [l_n, r_n]\) ( \(1\le l_i < r_i\le 2n\) )。保证每条线段的端点为整数,且 \(\forall i, j\) ( \(i \ne j\) ),不存在 \(l_i = l_j\) 或 \(r_i = r_j\),不存在 \(r_i = l_j\)。

现在用这 \(n\) 个点构建一个图,结点 \(u, v\) 有边相连当且仅当 \([l_u, r_u]\) 和 \([l_v, r_v]\) 相交,但其中任意一个均不包含另一个。

你的任务是判断这个图是否是一棵树。

题解

题解

考虑一个图成为一棵树的充分必要条件:所有点互相联通,并且一共有 \(n - 1\) 条边。

考虑 \(i, j\) 能连边的条件:

  1. \(l_i < l_j\)
  2. \(l_j < r_i < r_j\)。

于是将线段按左端点排序之后可以用二维偏序求出边的数量。

接着考虑使用并查集维护联通块,用 set <pair <int, int> > 插入 make_pair(r_i, i) 后将所有满足 \(l_j < r_i < r_j\) 的 \(i, j\) 连边即可。

这里有个细节,一定要在求完边数量并确保它等于 \(n - 1\) 后再连边,否则连边的数量可能会到 \(\mathcal{O}(n^2)\)。

code:

#include <bits/stdc++.h>
#include <cmath>
using namespace std;
int n;
vector <int> c, fa;
vector <pair <int, int> > tg;
set <pair <int, int> > s;
void insert(int x, int v) {for (; x <= 2 * n; x += x & -x) c[x] += v;}
int query(int x) {int r = 0; for (; x; x -= x & -x) r += c[x]; return r;}
signed main(void) {
    ios :: sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    cin >> n;
    c.assign(2 * n + 1, 0);
    tg.assign(2 * n + 1, {});
    fa.assign(n, 0);
    for (int i(0); i < n; ++i) fa[i] = i;
    function <int(int)> find = [&](int x) {
        return x == fa[x] ? x : fa[x] = find(fa[x]);
    } ;
    for (int i(0); i < n; ++i) {
        int l, r; cin >> l >> r;
        tg[l] = make_pair(r, i);
        tg[r] = make_pair(-l, i);
    }
    unsigned long long ans = 0;
    for (int i(1); i <= 2 * n; ++i) {
        int kl, kr; tie(kl, kr) = tg[i];
        if (kl < 0) insert(-kl, -1);
        else ans += query(kl) - query(i), insert(kl, 1);
    }
    if (ans != n - 1) return (cout << "NO\n"), 0;
    for (int i(1); i <= 2 * n; ++i) {
        int kl = tg[i].first, kr = tg[i].second;
        if (kl < 0) s.erase(s.find(make_pair(i, kr)));
        else {
            auto k = s.lower_bound(make_pair(i, 0));
            for (auto k = s.lower_bound(make_pair(i, 0)); k != s.end() && k -> first < kl; k = next(k)) {
                int father = find(k -> second);
                fa[father] = find(kr);
            }
            s.insert(make_pair(kl ,kr));
        }
    }
    bool flg = 0;
    for (int i(1); i < n; ++i) if (find(i) != find(0)) flg = 1;
    cout << (!flg ? "YES\n" : "NO\n");
    return 0;
}

标签:int,题解,make,Codeforces,1278D,fa,tg,find
From: https://www.cnblogs.com/CTHOOH/p/17739160.html

相关文章

  • P5943 [POI2002] 最大的园地 题解
    题目传送门前置知识单调栈简化题意在一个\(n\timesn\)的正方形内找到最大的由\(0\)组成的子矩形的面积。解法令\(f_{i,j}(1\lei,j\len)\)表示从\((1,j)\)到\((i,j)\)中以\((i,j)\)结尾的均为\(0\)的子串长度,即\((i,j)\)上面可延伸的最大距离(子矩形的......
  • Codeforces Round 811 (Div. 3)
    A.EveryoneLovestoSleep#include<bits/stdc++.h>usingnamespacestd;voidsolve(){intn,h,m,t;cin>>n>>h>>m;t=h*60+m;vector<int>a;for(inti=1,x,y;i<=n;i++)cin......
  • Codeforces 1702G2 题解
    题目大意给出一个大小为\(n\)的树,\(q\)次询问,每次给出一个大小为\(m\)的点集,判断是否有一条链覆盖这些点(这条链可以经过其他点)。\(n,\summ\leqslant2\cdot10^5\),\(q\leqslant10^5\)。提示提示1思考将$m$个点按深度排序。题解题解考虑将\(m\)个点按树......
  • CodeForces 1874B Jellyfish and Math
    洛谷传送门CF传送门看到这种操作乱七八糟不能直接算的题,可以考虑最短路。对于\(a,b,c,d,m\)按位考虑,发现相同的\((a,b,m)\)无论如何操作必然还是相同的。于是考虑对于每个可能的\((0/1,0/1,0/1)\),所有终态有\((c=0/1,d=0/1)\)或者不确定。这样我们对于一......
  • ABC322G题解
    这场的G怎么这么毒瘤啊/kk听说正解是DP?我爆搜头一个表示不服!statement找出三元组\((S,a,b)\)的数量,使得\(S\)在\(a\)进制下和在\(b\)进制下的差为\(X\),其中\(0\leqS_i<(min(a,b,10))\)。首先因为\(X>0\)显然\(S\)不可能为\(1\)位数。如果\(S\)......
  • 「题解」Codeforces Round 895 (Div. 3)
    A.TwoVesselsProblem题目Sol&Code签到题#include<bits/stdc++.h>typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}intT,a,b,c;intmain(){scanf("%d"......
  • AT_abc254_h [ABC254Ex] Multiply or Divide by 2 题解
    打篇题解巩固一下。题意给你两个集合\(A\)和\(B\),对于任意\(A\)集合中的元素,我们可以进行\(2\)种操作:\(a_i\gets\left\lfloor\frac{a_i}{2}\right\rfloor\)或\(a_i\gets2\timesa_i\)。问最少要多少次才能使\(A\)和\(B\)中的元素相等。分析首先我们可以令\(a......
  • UVA12655 Trucks 题解
    题目传送门前言中文题目可以看link。前置知识Kruskal重构树|最近公共祖先简化题意给定一个\(N\)个点\(M\)条边的有向图,共有\(S\)次询问,每次询问从\(L\)到\(H\)所有的路径中最小的权值的最大值(多组数据)。本题即最大瓶颈路问题。解法使最小的权值最大,不难......
  • 【洛谷 P1305】新二叉树 题解(结构体数组+先序遍历+二叉树)
    新二叉树题目描述输入一串二叉树,输出其前序遍历。输入格式第一行为二叉树的节点数。()后面行,每一个字母为节点,后两个字母分别为其左右儿子。特别地,数据保证第一行读入的节点必为根节点。空节点用*表示输出格式二叉树的前序遍历。样例#1样例输入#16abcbdicj*d**i**j**......
  • SP16113 SUBTLEBA - Trucks Transportation 题解
    题目传送门前言本题样例有问题,如果想要样例可以去vjudge上。本题提交后可能会出现UKE,建议前往link提交,而且本篇题解中所提供的代码也为link代码。前置知识Kruskal重构树|最近公共祖先简化题意给定一个\(N\)个点\(M\)条边的有向图,共有\(S\)次询问,每次询问......