Description
给你一个长度为len的环,以及n个区间,要你选择尽量少的区间,使得它们完全覆盖整个环。问最少要多少个区间。
Input
输入数据的第一行是两个整数len和n,代表环的长度以及区间个数。之后n行描述的是n个区间,每个区间分别用一对数字(a,b)表示,若a≤b则表示这个区间覆盖的是[a,b]部分,否则表示这个区间覆盖的是除掉[a+1,b-1]以外的其他部分。
Output
输出只有一行,一个整数,代表覆盖整个环所需要的最少区间个数。
Sample Input
100 7
1 50
50 70
70 90
90 40
20 60
60 80
80 20
Sample Output
3
一开始以为是什么区间问题,认真想了想觉得链的话随便做,环的话?
然后试了一下好像不能过。。没啥想法了,%一波po姐。
每个区间向它能跳到且右端点最远的区间连边,形成一棵树。
然后倍增一下,每个点向上倍增最少多少步可以走完这整个环。
nlogn居然能过。。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e6+5;
const int inf=0x3f3f3f3f;
int n,len,mn[N],fa[N][25];
struct node
{
int l,r;
}a[N];
int ans;
bool cmp(node a,node b)
{
return a.r<b.r;
}
int main()
{
scanf("%d%d",&len,&n);
fo(i,1,n)
{
scanf("%d%d",&a[i].l,&a[i].r);
if (a[i].r<a[i].l)a[i].r+=len;
}
sort(a+1,a+1+n,cmp);
mn[n+1]=inf;
fd(i,n,1)mn[i]=min(a[i].l,mn[i+1]);
int j=1;
fo(i,1,n)
{
while (j<n&&mn[j+1]-1<=a[i].r)j++;
if (j!=i)fa[i][0]=j;
}
fd(i,n,1)
fo(j,1,20)fa[i][j]=fa[fa[i][j-1]][j-1];
ans=inf;
fo(i,1,n)
{
int x=i,s=1;
fd(j,20,0)if (fa[x][j]&&a[fa[x][j]].r<a[i].l+len)x=fa[x][j],s+=1<<j;
if (a[x].r<a[i].l+len-1&&fa[x][0])x=fa[x][0],s++;
if (a[x].r>=a[i].l+len-1)ans=min(ans,s);
}
if (ans==inf)puts("impossible");
else printf("%d\n",ans);
}