ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

F. The Treasure of The Segments

2020-12-21 15:35:10  阅读:242  来源: 互联网

标签:std int Segments Treasure maxn ans 线段 define


题意:

给出n个线段组成的集合,第i个线段用 \(\{l_i, r_i\}\) 表示线段从坐标轴的点\(l_i\)横跨到点\(r_i\)。现在你可以删除其中的一些线段,使得剩下的线段组成的集合中至少存在一个线段满足:这个线段与所有其他线段都相交。现在问你最少需要删除几条边可以得到满足要求的线段集合。

思路:

我们枚举每个线段,让这个线段能够与所有其他线段相交,这时候我们只需要算出不和这个边相交的线段的个数。算这个的方法也很简单,可以想一下什么情况下两个线段 \(\{l_1, r_1\}\) \(\{l_2, r_2\}\) 不相交,也就是 \(l_2 > r1\) 或者 \(r_2 < l_1\) 的情况下,两个边就不会相交。所以我们可以用两个数组来分别存储边的\(l\) 和\(r\),排序之后,就可以用二分来快速找到不与当前枚举的边相交的边的个数。

小注:

之前有看其他博主写的博客,有提到二分比较难写,主要是因为没有善用\(lower\_bound\)和\(upper\_bound\)。

AC代码:

#include <cstdio>
#include <algorithm>

#define pii pair<int, int>
#define fr first
#define sc second

const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;

std::pii a[maxn];
int l[maxn], r[maxn];

int main () {
    int T, n;
    scanf ("%d", &T);
    while (T--) {
        scanf ("%d", &n);
        for (int i = 0; i < n; i++) {
            scanf ("%d %d", &a[i].fr, &a[i].sc);
            l[i] = a[i].fr;
            r[i] = a[i].sc;
        }
        std::sort (l, l + n);
        std::sort (r, r + n);
        int ans = inf;
        for (int i = 0; i < n; i++) {
            int tot = 0;
            tot = 0;
            tot += (int)(std::lower_bound(r, r + n, a[i].fr) - r);
            tot += n - (int)(std::upper_bound(l, l + n, a[i].sc) - l);
            ans = std::min (ans, tot);
        }
        printf ("%d\n", ans);
    }
  	return 0;
}

这题一开始没想到那么简洁的做法,最开始用线段树维护不和当前枚举的线段相交的个数,结果。。。T了。

杀鸡用牛刀超时未AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

#define pii pair<int, int>
#define mp(a, b) make_pair(a, b)
#define fr first
#define sc second

const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;

std::pii in[maxn], num[maxn];
int lisan[maxn << 1], tot_lisan = 1;

class seg_tree {
public:
    int tree[maxn << 2];

    void init() {
        memset (tree, 0, sizeof tree);
    }

    void push_up (int p) {
        tree[p] = tree[p << 1] + tree[p << 1 | 1];
    }

    void update (int p, int l, int r, int idx) {
        if (l == r) {
            tree[p]++;
        } else {
            int mid = (l + r) >> 1;
            if (idx <= mid) {
                update (p << 1, l, mid, idx);
            } else {
                update (p << 1 | 1, mid + 1, r, idx);
            }
            push_up(p);
        }
    }

    int query (int p, int l, int r, int ql, int qr) {
        if (r < ql || l > qr) {
            return 0;
        } else if (l >= ql && r <= qr) {
            return tree[p];
        } else {
            int mid = (l + r) >> 1;
            int ans = 0;
            ans += query (p << 1, l, mid, ql, qr);
            ans += query (p << 1 | 1, mid + 1, r, ql, qr);
            return ans;
        }
    }
}t1, t2;

int main () {
    int T, n;
    scanf ("%d", &T);
    while (T--) {
        t1.init();
        t2.init();
        tot_lisan = 1;
        memset (num , 0, sizeof num);
        scanf ("%d", &n);
        for (int i = 0; i < n; i++) {
            int l, r;
            scanf ("%d %d", &l, &r);
            in[i] = std::mp(l, r);
            lisan[tot_lisan++] = l;
            lisan[tot_lisan++] = r;
        }
        std::sort (lisan, lisan + tot_lisan);
        std::sort (in, in + n);
        tot_lisan = (int)(std::unique(lisan, lisan + tot_lisan) - lisan);
        for (int i = 0; i < n; i++) {
            int pl = (int)(std::lower_bound(lisan, lisan + tot_lisan, in[i].fr) - lisan);
            int pr = (int)(std::lower_bound(lisan, lisan + tot_lisan, in[i].sc) - lisan);
            num[i].fr = pl;
            num[i].sc = pr;
            t1.update (1, 0, tot_lisan, pl);
            t2.update (1, 0, tot_lisan, pr);
        }
        int ans = inf;
        for (int i = 0; i < n; i++) {
            int pl = num[i].fr;
            int pr = num[i].sc;
            int tot = 0;
            tot += t1.query (1, 0, tot_lisan, pr + 1, tot_lisan);
            tot += t2.query (1, 0, tot_lisan, 0, pl - 1);
            ans = std::min (ans, tot);
        }
        printf ("%d\n", ans);
    }
    return 0;
}

标签:std,int,Segments,Treasure,maxn,ans,线段,define
来源: https://www.cnblogs.com/chantmee/p/14168074.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有