E. Delete a Segment

E. Delete a Segment

题意:有n个线段 让你从中人选一个 将其删除问最后 有多少不连续的线段,求最大的。

题解:这题我刚开始写的时候就知道线段树可以做,但是 来来回回折腾了两天才把这题ac了,第一题写没考虑离散化会有bug。写说一下,我是怎么写的吧!第一天 我是先离散化,然后将每个线段插入到线段树中(这线段树有点类似与扫描线中的线段树,至于为啥这样,你学了扫描线就知道了),但是写着写着发现了bug比如现在有两个线段 (1,4)(10,18)很明显有两条不连续的但是离散化后是(1,2)(3,4)但是这样虽然是两端不连续的,但是再线段树中这是两个节点,按照我的写法回是1个不连续的,所以要在离散化中进行处理 将所有边都乘2 (2,8)(20,36),然后再加入四条边(3,8) (2,9) (21,36) (20,37)这样离散化后就是(1,3), (5 , 7)再线段树就是查就是两个不连续的线段了。

还有个难点就是线段树回溯的过程,我可以再每个节点中有两个值流lc,rc来记录这个节点的线段左右是否有边,然后合并的时候,左儿子 lc有 ,右儿子rc有,那就再两个节点之后中减1.

看代码吧:

#include<bits/stdc++.h>
using namespace std;

const int N = 2e5 + 7;
int n, t,flag[30*N];

struct node{
    int l, r;
} p[N];

struct power{
    int counts;
    int lc, rc;
    int l, r;
} tree[30 * N];

vector<int> v;

#define m (l+r)/2
#define lson 2*node
#define rson 2*node+1

void build(int l,int r,int node){
    tree[node].counts = tree[node].lc = tree[node].rc = 0;
    tree[node].l = l;
    tree[node].r = r;
    flag[node] = 0;
    if(l == r){
        tree[lson].l = l;
        tree[lson].r = l;
        tree[lson].counts = tree[lson].lc = tree[lson].rc = 0;
        tree[rson].l = r;
        tree[rson].r = r;
        tree[rson].counts = tree[rson].lc = tree[rson].rc = 0;
        flag[lson] = flag[rson] = 0;
        return;
    }
       
    build(l, m, lson);
    build(m+1 , r, rson);
}

void push_up(int node){
    if(flag[node]){
        tree[node].counts = 1;
        tree[node].lc = flag[node];
        tree[node].rc = flag[node];
    }else{
        tree[node].counts = tree[lson].counts + tree[rson].counts;
        if(tree[lson].rc && tree[rson].lc)
            tree[node].counts--;
        tree[node].lc = tree[lson].lc;
        tree[node].rc = tree[rson].rc;
    }
}

void update(int v,int ql,int qr,int node){
    if(tree[node].l > qr || tree[node].r < ql)
        return;
    if(tree[node].l >=ql && tree[node].r <= qr){
        flag[node] += v;
        push_up(node);
        return;
    }
    update(v, ql, qr, lson);
    update(v, ql, qr, rson);
    push_up(node);
}

int get_id(int x){
    return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}



int main(){
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        for (int i = 1; i <= n; i++){
            scanf("%d%d", &p[i].l, &p[i].r);
            p[i].l *= 2;
            p[i].r *= 2;
            v.push_back(p[i].l);
            v.push_back(p[i].r);
            v.push_back(p[i].l + 1);
            v.push_back(p[i].r + 1);
        }
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        build(1, v.size(), 1);
        for (int i = 1; i <= n;i++){
            int l = get_id(p[i].l);
            int r = get_id(p[i].r);
            update(1, l, r, 1);
        }
        int ans = 0;
        for (int i = 1; i <= n;i++){
            int l = get_id(p[i].l);
            int r = get_id(p[i].r);
            update(-1, l, r, 1);
            ans = max(ans, tree[1].counts);
            update(1, l, r, 1);
        }
        printf("%d\n", ans);
        build(1, v.size(), 1); 
        v.clear();
    }
}


发布了10 篇原创文章 · 获赞 1 · 访问量 181

猜你喜欢

转载自blog.csdn.net/weixin_45676038/article/details/104011140