SCOI2015 国旗计划

本文介绍了一种解决环形区间覆盖问题的高效算法,通过将环形区间转换为链状结构,利用二分查找和倍增技巧,实现O(nlogn)的时间复杂度。文章详细解释了算法思路,包括区间排序、最优选择区间确定及倍增预处理等关键步骤。

Link

Diffculty

算法难度5,思维难度6,代码难度5

Description

给定一个长度为 m m m的环,环上有 m m m个点 [ 1 , m ] [1,m] [1,m],以及 n n n个互不包含的区间。

要求对于每个区间求出,在必须选这个区间的前提下,能使得所有被选区间覆盖整个环的最少区间数。

1 ≤ n ≤ 2 × 1 0 5 , m &lt; 1 0 9 1\le n\le 2\times 10^5,m&lt;10^9 1n2×105,m<109

Solution

首先区间互不包含,那么我们将所有区间按照左端点排序之后,区间一定满足左端点和右端点同时严格递增。

破环成链之后,这样我们可以二分或者递推求出选每个区间的下一个最优选择区间。

求出来之后,比如第 i i i个区间的下一个最优区间是 f ( i ) f(i) f(i),那么就从 f ( i ) f(i) f(i) i i i连一条边。

这样我们倍增预处理每个点的 2 j 2^j 2j级祖先,查询的时候就固定这个区间开始,限制不能再跳过这个区间的左端点,然后直接倍增跳就好了,最后加上没有算的这两个区间。

时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
inline int read(){
    int x=0,f=1;char ch=' ';
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')x=x*10+(ch^48),ch=getchar();
    return f==1?x:-x;
}
const int N=4e5+5;
struct data{
	int l,r,id;
	data(){}
	data(int _l,int _r,int _id):l(_l),r(_r),id(_id){}
	inline bool operator < (const data& b) const {
		return l<b.l;
	}
}a[N];
int n,m,c[N],d[N],tot,fa[N][19],ans[N];
int main(){
	n=read();m=read();
	for(int i=1;i<=n;++i){
		int l=read(),r=read();
		if(r<l)r+=m;
		a[++tot]=data(l,r,i);
		a[++tot]=data(l+m,r+m,0);
	}
	sort(a+1,a+tot+1);
	for(int i=1;i<tot;++i){
		int l=i+1,r=tot,mid;
		while(l<r){
			mid=(l+r+1)>>1;
			if(a[mid].l<=a[i].r)l=mid;
			else r=mid-1;
		}
		fa[i][0]=l;
	}
	for(int k=1;k<=18;++k)
		for(int i=1;i<=tot;++i)
			fa[i][k]=fa[fa[i][k-1]][k-1];
	for(int i=1;i<=tot;++i){
		if(!a[i].id)continue;
		int x=i,L=a[i].l+m;
		for(int j=18;j>=0;--j)
			if(fa[x][j] && a[fa[x][j]].r<L)
				x=fa[x][j],ans[a[i].id]+=(1<<j);
	}
	for(int i=1;i<=n;++i)printf("%d ",ans[i]+2);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值