首先把环写两遍展开。
然后考虑必须选一个区间,只需要把这个区间作为最左边的区间开始选(因为如果左面还有区间等价于放到右面处理)。
用倍增维护这个过程即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#define N 400010
#define LOG 21
#define INF (LLONG_MAX/10-10)
#define lint long long
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
struct P{
lint l,r;int id;
inline bool operator<(const P &p)const { return l<p.l; }
}p[N];int nxt[N][LOG],ans[N];
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
char ss[N*20],tt[20];int ssl,ttl;
inline int show(int x)
{
if(!x) ss[++ssl]='0';
for(ttl=0;x;x/=10) tt[++ttl]=x%10+'0';
for(;ttl;ttl--) ss[++ssl]=tt[ttl];
return ss[++ssl]=' ';
}
int main()
{
int n=inn(),m=inn();
for(int i=1;i<=n;i++)
{
int x=inn(),y=inn();if(x>y) y+=m;p[i+n].id=0;
p[i].id=i,p[i+n].l=(p[i].l=x)+m,p[i+n].r=(p[i].r=y)+m;
}
sort(p+1,p+2*n+1),p[2*n+1].l=INF;
for(int i=2*n,j=2*n+1;i;i--)
{
while(j&&p[j].l>p[i].r) j--;
if(p[j].l<=p[i].r) nxt[i][0]=j;
}
for(int j=1;j<LOG;j++)
for(int i=1;i<=2*n;i++)
nxt[i][j]=nxt[nxt[i][j-1]][j-1];
for(int i=1;i<=2*n;i++) if(p[i].id)
for(int j=LOG-1,x=i;j>=0;j--)
if(nxt[x][j]&&p[nxt[x][j]].r<p[i].l+m)
x=nxt[x][j],ans[p[i].id]+=1<<j;
for(int i=1;i<=n;i++) show(ans[i]+2);ss[++ssl]='\n';
return fwrite(ss+1,sizeof(char),ssl,stdout),0;
}