題目
這個題要是真的打倍增就是思維僵化,莫得洗白。
如果把每個,對於並且在此基礎上滿足最大的的我們連邊,我們把環拆成長度爲的鏈後這種連邊就會連出來一棵樹,那麼每個點的答案就是祖先中最後一個與距離一個環長的點與在樹上的深度差。
所以解法一:樹上DFS+當前弧優化
大佬代碼
解法二:排序求出樹上點反向拓撲序即可用並查集優化。
#include<bits/stdc++.h>
#define maxn 400005
using namespace std;
int n,m,p,c[maxn],d[maxn],id[maxn],ans[maxn];
bool cmp(const int &u,const int &v){ return c[u]<c[v]; }
int F[maxn],D[maxn];
int Find(int u){
int t = F[u];
if(t<p) F[u] = Find(t) , D[u] += D[t];
return F[u];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d%d",&c[i],&d[i]),id[i]=i,(d[i]<c[i]?d[i]+=m:0);
sort(id+1,id+1+n,cmp);
for(int i=1;i<=n;i++) id[i+n]=id[i]+n,c[i+n]=c[i]+m,d[i+n]=d[i]+m;
for(int i=1,j=2;i<=2*n;i++){
for(;j<=2*n && c[id[j]] <= d[id[i]];j++);
F[i] = j-1 , D[i] = 1;
}
for(int i=1;i<=n;i++){
p=i+n,Find(i);
ans[id[i]] = D[i];
}
for(int i=1;i<=n;i++) printf("%d%c",ans[i]," \n"[i==n]);
}