国旗计划 解题报告
题目描述
一看 \(n\) 高达 \(2e5\),直接猜时间复杂度为 \(O(NlogN)\) 的算法。
环上问题,先破环为链。
我们可以考虑对于一个区间,它可以转移到左端点在这个区间内的任意一个区间,所以通过贪心的思想可以得到,我们肯定要取左端点最大的一个区间。
同时我们注意到,一个一个区间跳显然太慢了,所以我们考虑倍增。
常见错因:
- 没有按照输入顺序输出答案
- 没有在破环为链中将每一个区间都复制一份
Talk is cheap,show me your code
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ls (i<<1)
#define rs (i<<1|1)
using namespace std;
inline int max(int x,int y){return x>y?x:y;}
const int N=4e5+1000;
typedef long long ll;
int n,m,len,b[N*3],cnt;
struct Node{int l,r,ed;}a[N];
int f[N][19];
bool cmp(Node x,Node y){return x.l<y.l;}
void init(){
for(int i=1;i<=cnt;i++) b[i*3-2]=a[i].l,b[i*3-1]=a[i].r,b[i*3]=a[i].ed;
sort(b+1,b+3*cnt+1,less<int>());
len=unique(b+1,b+3*cnt+1)-b-1;
for(int i=1;i<=cnt;i++){
a[i].l=lower_bound(b+1,b+len+1,a[i].l)-b;
a[i].r=lower_bound(b+1,b+len+1,a[i].r)-b;
a[i].ed=lower_bound(b+1,b+len+1,a[i].ed)-b;
}
sort(a+1,a+cnt+1,cmp);
}
typedef pair<int,int> pii;
struct Tree{int l,r;pii val;}t[N<<3];
void push_up(int i){t[i].val=max(t[ls].val,t[rs].val);}
void build(int i,int l,int r){
t[i].l=l,t[i].r=r;
if(l==r)
return;
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
void update(int i,int x,pii k){
if(t[i].l==t[i].r){
t[i].val=k;
return;
}
int mid=t[i].l+t[i].r>>1;
if(x<=mid) update(ls,x,k);
else update(rs,x,k);
push_up(i);
}
pii ans;
void query(int i,int l,int r){
if(l<=t[i].l && t[i].r<=r){
ans=max(ans,t[i].val);
return;
}
int mid=t[i].l+t[i].r>>1;
if(l<=mid) query(ls,l,r);
if(mid<r) query(rs,l,r);
}
int main()
{
//freopen("banquet.in","r",stdin);
//freopen("banquet.out","w",stdout);
scanf("%d%d",&n,&m),cnt=n;
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].l,&a[i].r);
a[i].ed=a[i].l+m;
if(a[i].l>=a[i].r) a[i].r+=m;
if(a[i].r<=m)
++cnt,a[cnt].l=a[i].l+m,a[cnt].r=a[i].r+m;
}
init();
build(1,1,len);
for(int i=1;i<=cnt;i++)
update(1,a[i].l,make_pair(a[i].r,i));
for(int i=1;i<=cnt;i++){
query(1,a[i].l,a[i].r);
f[i][0]=ans.second;
}
for(int i=cnt;i>=1;i--)
for(int j=1;j<=18;j++)
f[i][j]=f[f[i][j-1]][j-1];
a[0].r=inf;
for(int i=1,u,ans;i<=n;i++){
u=i,ans=0;
for(int j=18;j>=0;j--)
if(a[f[u][j]].r<a[i].ed)
u=f[u][j],ans+=(1<<j);
printf("%d ",ans+2);
}
return 0;
}

浙公网安备 33010602011771号