题意:有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();
}
}