断环为链。将端点离散,令
fi
表示左端点小于等于
i
的右端点的最大值。那么显然当右端点为
因为每个区间的答案一定小于等于最优答案加
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
#define fi first
#define se second
typedef pair<int,int> abcd;
const int N=400010;
vector<int>g[N<<1];
int q[N<<1],R;
abcd c[N<<1];
int k,n,m,p;
int l[N],r[N];
int f[N<<1],Ans[N<<1];
int num,cnt;
int x,y,top,d[N<<1];
void Dfs(int x,int y){
d[x]=y;
while(p<R-1&&q[p+1]>=x+m)p++;
if(x<=num)Ans[x]=d[x]-d[q[p]];
q[R++]=x;
for(int i=0;i<g[x].size();i++){
Dfs(g[x][i],y+1);
while(p&&q[p]<x+m)p--;
R--;
}
}
int main(){
Read(n);Read(m);
for(int i=1;i<=n;i++)Read(x),Read(y),c[++cnt]=abcd(x,i),c[++cnt]=abcd(y,i+n);
sort(c+1,c+cnt+1);
for(int i=1;i<=cnt;i++){
if(c[i].fi!=c[i-1].fi)num++;
if(c[i].se>n)r[c[i].se-n]=num;else l[c[i].se]=num;
}
if(c[cnt].fi<m)m=++num;else m=num;
for(int i=1;i<=n;i++)
if(r[i]>=l[i]){
f[l[i]]=max(f[l[i]],r[i]);
f[l[i]+num]=max(f[l[i]+num],r[i]+num);
}else{
f[1]=max(f[1],r[i]);
f[l[i]]=max(f[l[i]],r[i]+num);
f[l[i]+num]=max(f[l[i]+num],num<<1);
}
for(int i=1;i<=(num<<1);i++){
f[i]=max(f[i],f[i-1]);
if(f[i]>i)g[f[i]].push_back(i);
}
for(int i=num+1;i<=(num<<1);i++)
if(f[i]<=i)p=R=0,Dfs(i,0);
for(int i=1;i<=n;i++)printf("%d ",Ans[l[i]]);
return 0;
}