拆环成链+贪心区间覆盖+倍增
好题,先插个眼,以后水平上来了再看
https://www.luogu.com.cn/problem/P4155
#include<bits/stdc++.h>
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const double pi=acos(-1);
const int N=4e5+5;
int n,m,tn;
struct Node{
int id,l,r;
bool operator < (const Node t)const {return l<t.l;}
}a[N*2];
int nxt[N][20],ans[N]; //定义nxt[s][i]为从第s个区间出发,走2^i个最优区间后到达的区间
void init(){
int nx=1;
// 贪心求出下一个右端点最大的区间
for(int i=1;i<=tn;i++){
while(nx<=tn and a[nx].l<=a[i].r){
nx++;
}
nxt[i][0]=nx-1;
}
// 倍增,遍历区间后的第2^i个区间
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j<=tn;j++){
nxt[j][i]=nxt[nxt[j][i-1]][i-1]; //倍增递推式
}
}
}
void go(int x){ //从第x个位置出发
int len=a[x].l+m,now=x,res=1;
for(int i=log2(N);i>=0;i--){ //从最大i开始找
int pos=nxt[now][i];
if(pos and a[pos].r<len){
res+=1<<i; //累加跳过的不优区域
now=pos; //新位置重新开始
}
}
ans[a[x].id]=res+1;
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++){
a[i].id=i;
cin>>a[i].l>>a[i].r;
if(a[i].r<a[i].l) a[i].r+=m;
}
sort(a+1,a+n+1);
tn=n;
for(int i=1;i<=n;i++){
tn++;
a[tn]=a[i];
a[tn].l=a[i].l+m;
a[tn].r=a[i].r+m;
}
init();
for(int i=1;i<=n;i++) go(i);
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
}
signed main(){
ios::sync_with_stdio(false);cin.tie(nullptr);
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}