[SCOI2015]国旗计划
BZOJ
luogu
先考虑破环为链
由于区间不包含,我们sort之后可以贪心的选左端点在当前右端点之前的最后一个
然后预处理一个倍增数组,每次logn查一下
复杂度(O(nlogn))
空间两倍,tot+1的r设为inf
#include<bits/stdc++.h>
using namespace std;
const int _=4e5+5;
int re(){
int x=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
int n,m,tot,ans[_],f[20][_];
struct node{int l,r,id;}s[_];
bool cmp(node a,node b){return a.r<b.r;}
int solve(int x,int R){
int res=0;
for(int i=18;i>=0;i--)
if(s[f[i][x]].r<R){
res+=(1<<i);
x=f[i][x];
}
return res+2;
}
int main(){
tot=n=re(),m=re();
for(int i=1;i<=n;i++){
int l=re(),r=re();
if(l>r)s[i]=(node){l,r+m,i};
else s[i]=(node){l,r,i},s[++tot]=(node){l+m,r+m};
}
sort(s+1,s+tot+1,cmp);s[0].r=s[tot+1].r=2e9+1;
for(int i=1,j=1;i<=tot;i++){
while(s[j+1].l<=s[i].r&&j<=tot)j++;
f[0][i]=j;
}
for(int i=1;i<=18;i++)
for(int j=1;j<=tot;j++)
f[i][j]=f[i-1][f[i-1][j]];
for(int i=1;i<=n;i++)
ans[s[i].id]=solve(i,s[i].l+m);
for(int i=1;i<=n;i++)printf("%d ",ans[i]);
return 0;
}