[SCOI2015]国旗计划

[SCOI2015]国旗计划

BZOJ
luogu
先考虑破环为链
由于区间不包含,我们sort之后可以贪心的选左端点在当前右端点之前的最后一个
然后预处理一个倍增数组,每次logn查一下
复杂度(O(nlogn))
空间两倍,tot+1的r设为inf

#include<bits/stdc++.h>
using namespace std;
const int _=4e5+5;
int re(){
    int x=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*w;
}
int n,m,tot,ans[_],f[20][_];
struct node{int l,r,id;}s[_];
bool cmp(node a,node b){return a.r<b.r;}
int solve(int x,int R){
    int res=0;
    for(int i=18;i>=0;i--)
        if(s[f[i][x]].r<R){
            res+=(1<<i);
            x=f[i][x];
        }
    return res+2;
}
int main(){
    tot=n=re(),m=re();
    for(int i=1;i<=n;i++){
        int l=re(),r=re();
        if(l>r)s[i]=(node){l,r+m,i};
        else s[i]=(node){l,r,i},s[++tot]=(node){l+m,r+m};
    }
    sort(s+1,s+tot+1,cmp);s[0].r=s[tot+1].r=2e9+1;
    for(int i=1,j=1;i<=tot;i++){
        while(s[j+1].l<=s[i].r&&j<=tot)j++;
        f[0][i]=j;
    }
    for(int i=1;i<=18;i++)
        for(int j=1;j<=tot;j++)
            f[i][j]=f[i-1][f[i-1][j]];
    for(int i=1;i<=n;i++)
        ans[s[i].id]=solve(i,s[i].l+m);
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/sdzwyq/p/9891128.html