bzoj4444: [Scoi2015]国旗计划

流年不利啊最近。。。要么就是要了数据只WA一个点。。。要么就是WA成一片还是一个一个点调对。。。

这题很明显就是贪心了,离线后按l排序(记得要复制一份放在后面,对于环这是常规操作了吧),由于没有覆盖,对于一个l~r的区间,下一个接棒的左端点一定是最接近右边界的,可以预处理出来,最后用倍增的思想出解。

一开始打了个沙茶的玄学复杂度dfs是什么鬼。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n,m;
struct query
{
    int l,r,id;
    friend bool operator <(query q1,query q2){return q1.l<q2.l;}
}q[410000];int qlen;
void qins(int l,int r,int id)
{
    qlen++;
    q[qlen].l=l;q[qlen].r=r;q[qlen].id=id;
}

int f[30][410000];
int as[410000];
int main()
{
    freopen("flag.in","r",stdin);
    freopen("flag.out","w",stdout);
    scanf("%d%d",&n,&m);
    qlen=0;
    for(int i=1;i<=n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(x>y)y+=m;
        qins(x,y,i);
        qins(x+m,y+m,0);
    }
    sort(q+1,q+qlen+1);
    memset(f,0,sizeof(f));
    for(int i=1;i<=qlen;i++)
    {
        query tt;tt.l=q[i].r;
        f[0][i]=upper_bound(q+1,q+qlen+1,tt)-q-1;
        if(f[0][i]==i)f[0][i]=0;
    }
    for(int i=qlen;i>=1;i--)
    {
        for(int j=1;f[j-1][f[j-1][i]]!=0;j++)
            f[j][i]=f[j-1][f[j-1][i]];
    }
    
    for(int i=1;i<=qlen;i++)
    {
        if(q[i].id>0)
        {
            as[q[i].id]=0;
            int now=i;
            for(int j=25;j>=0;j--)
                if(f[j][now]>0&&q[f[j][now]].r-q[i].l<m)
                    as[q[i].id]+=(1<<j), now=f[j][now];
            as[q[i].id]++;
        }
    }
    
    for(int i=1;i<n;i++)printf("%d ",as[i]+1);
    printf("%d\n",as[n]+1);
    return 0;
}

 

posted @ 2018-04-20 09:14  AKCqhzdy  阅读(143)  评论(0编辑  收藏  举报