预处理出对于每个区间
[
l
i
,
r
i
]
[l_i,r_i]
[li,ri] ,满足
r
i
<
l
j
r_i<l_j
ri<lj 且
r
j
r_j
rj 最小的区间
[
l
j
,
r
j
]
[l_j,r_j]
[lj,rj]
下文称之为「
i
i
i 的后继为
j
j
j 」
考虑一个小问题
查询在包含于
[
L
,
R
]
[L,R]
[L,R] 的所有区间中,最多能选出多少个互不相交的区间
先找到包含于
[
L
,
R
]
[L,R]
[L,R] 且右端点最小的区间
[
l
i
,
r
i
]
[l_i,r_i]
[li,ri] (不存在则答案为
0
0
0 )
问题转化为
i
i
i 至少跳多少次后继之后右端点超过
R
R
R 或者不存在后继
倍增
O
(
n
log
n
)
O(n\log n)
O(nlogn) 预处理后
O
(
log
n
)
O(\log n)
O(logn) 查询
考虑贪心地编号从小往大,考虑每个区间是否可以成为答案
设当前考虑区间
[
l
,
r
]
[l,r]
[l,r]
如果
[
l
,
r
]
[l,r]
[l,r] 内存在一点,已经被之前选出的区间覆盖,则这个区间不能成为答案
否则设
l
0
l_0
l0 为满足
[
l
0
,
l
]
[l_0,l]
[l0,l] 都没有被覆盖的最小的
l
0
l_0
l0
r
0
r_0
r0 为满足
[
r
,
r
0
]
[r,r_0]
[r,r0] 都没有被覆盖的最大的
r
0
r_0
r0
设
q
u
e
r
y
(
l
,
r
)
query(l,r)
query(l,r) 表示包含于
[
l
,
r
]
[l,r]
[l,r] 的所有区间中最多选出多少个区间互不相交
如果
q
u
e
r
y
(
l
0
,
l
−
1
)
+
1
+
q
u
e
r
y
(
r
+
1
,
r
0
)
≠
q
u
e
r
y
(
l
0
,
r
0
)
query(l_0,l-1)+1+query(r+1,r_0)\ne query(l_0,r_0)
query(l0,l−1)+1+query(r+1,r0)̸=query(l0,r0) 则区间
[
l
,
r
]
[l,r]
[l,r] 不能成为答案
否则区间
[
l
,
r
]
[l,r]
[l,r] 可以成为答案,直接加入答案
复杂度
O
(
n
log
n
)
O(n\log n)
O(nlogn)
Code
#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define For(i, a, b) for (i = a; i <= b; i++)#define Rof(i, a, b) for (i = a; i >= b; i--)#define p2 p << 1#define p3 p << 1 | 1inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}constint N =2e5+5, M = N <<1, L = M <<2, LogN =20;int n, m, tm, tmp[M], fa[N][LogN], dep[N], ri[M], sum[L], add[L],
ansm, ans[N], pre0[L], suf0[L];
std::vector<int> itv[M];struct node
{int l, r;} a[N];voidbuild(int l,int r,int p){
sum[p]= add[p]=0;
pre0[p]= suf0[p]= r - l +1;if(l == r)return;int mid = l + r >>1;build(l, mid, p2);build(mid +1, r, p3);}voiddown(int p){
add[p2]+= add[p]; add[p3]+= add[p];
add[p]=0;}voidupt(int l,int r,int p){int mid = l + r >>1, lp0, rp0, ls0, rs0;
sum[p]= sum[p2]+ sum[p3]+(mid - l +1)* add[p2]+(r - mid)* add[p3];
lp0 = add[p2]?0: pre0[p2];
rp0 = add[p3]?0: pre0[p3];
ls0 = add[p2]?0: suf0[p2];
rs0 = add[p3]?0: suf0[p3];
pre0[p]= lp0 == mid - l +1? lp0 + rp0 : lp0;
suf0[p]= rs0 == r - mid ? rs0 + ls0 : rs0;}voidchange(int l,int r,int s,int e,int v,int p){if(l == s && r == e)return(void)(add[p]+= v);int mid = l + r >>1;down(p);if(e <= mid)change(l, mid, s, e, v, p2);elseif(s >= mid +1)change(mid +1, r, s, e, v, p3);elsechange(l, mid, s, mid, v, p2),change(mid +1, r, mid +1, e, v, p3);upt(l, r, p);}intask(int l,int r,int s,int e,int p){if(l == s && r == e)return sum[p]+(r - l +1)* add[p];int mid = l + r >>1, res;down(p);if(e <= mid) res =ask(l, mid, s, e, p2);elseif(s >= mid +1) res =ask(mid +1, r, s, e, p3);else res =ask(l, mid, s, mid, p2)+ask(mid +1, r, mid +1, e, p3);returnupt(l, r, p), res;}intaskpre0(int l,int r,int s,int e,int p){if(l == s && r == e)return add[p]?0: pre0[p];int mid = l + r >>1, res;down(p);if(e <= mid) res =askpre0(l, mid, s, e, p2);elseif(s >= mid +1) res =askpre0(mid +1, r, s, e, p3);else{int lp =askpre0(l, mid, s, mid, p2),
rp =askpre0(mid +1, r, mid +1, e, p3);
res = lp == mid - s +1? lp + rp : lp;}returnupt(l, r, p), res;}intasksuf0(int l,int r,int s,int e,int p){if(l == s && r == e)return add[p]?0: suf0[p];int mid = l + r >>1, res;down(p);if(e <= mid) res =asksuf0(l, mid, s, e, p2);elseif(s >= mid +1) res =asksuf0(mid +1, r, s, e, p3);else{int ls =asksuf0(l, mid, s, mid, p2),
rs =asksuf0(mid +1, r, mid +1, e, p3);
res = rs == e - mid ? rs + ls : rs;}returnupt(l, r, p), res;}intgetans(int l,int r){if(l > r)return0;if(!ri[l]|| a[ri[l]].r > r)return0;int i, u = ri[l], st = u;
Rof (i,17,0)if(fa[u][i]&& a[fa[u][i]].r <= r)
u = fa[u][i];return dep[st]- dep[u]+1;}intmain(){int i, j, k, sz;
n =read();
For (i,1, n){
a[i].l =read(); a[i].r =read();
tmp[++tm]= a[i].l;
tmp[++tm]= a[i].r;}
std::sort(tmp +1, tmp + tm +1);
m = std::unique(tmp +1, tmp + tm +1)- tmp -1;
For (i,1, n){
a[i].l = std::lower_bound(tmp +1, tmp + m +1, a[i].l)- tmp;
a[i].r = std::lower_bound(tmp +1, tmp + m +1, a[i].r)- tmp;}
For (i,1, n) itv[a[i].l].push_back(i);
For (i,1, n)if(!ri[a[i].l]|| a[i].r < a[ri[a[i].l]].r)
ri[a[i].l]= i;
Rof (i, m -1,1)
ri[i]=!ri[i]||!ri[i +1]? ri[i]+ ri[i +1]:(a[ri[i]].r < a[ri[i +1]].r ? ri[i]: ri[i +1]);
Rof (i, m,1){int sz = itv[i].size();
For (j,0, sz -1){int u = itv[i][j];
fa[u][0]= ri[a[u].r +1];
dep[u]= dep[ri[a[u].r +1]]+1;
For (k,0,16)
fa[u][k +1]= fa[fa[u][k]][k];}}build(1, m,1);
For (i,1, n){if(ask(1, m, a[i].l, a[i].r,1))continue;int l = a[i].l -asksuf0(1, m,1, a[i].l,1)+1,
r = a[i].r +askpre0(1, m, a[i].r, m,1)-1;if(getans(l, r)!=getans(l, a[i].l -1)+getans(a[i].r +1, r)+1)continue;
ans[++ansm]= i;change(1, m, a[i].l, a[i].r,1,1);}
std::cout << ansm << std::endl;
For (i,1, ansm)printf("%d ", ans[i]);
std::cout << std::endl;return0;}