zoukankan      html  css  js  c++  java
  • 【题解】【神奇校内PION模拟赛】国旗计划

    神奇校内POIN模拟赛 国旗计划

    神奇校内POIN模拟赛 国旗计划

    1 题外话

    高队,yyds

    2 sol

    先把n的环拆成(2n) 的链

    由于区间之间没有包含关系,将可选区间按左端点排序后右端点单调递增

    可以二分找到左端点在当前区间内的右端点最大的区间,每次如此贪心选即可

    考虑到时间复杂度(nlogn) 的要求,考虑倍增,(f_{i,j}) 表示从(j) 位置选择(2^i) 段区间最远能覆盖到哪

    倍增求解,最后加上差的最后一段和本身一段总计2个区间即可

    3 code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N=200010;
    
    inline void read(int &x) {
        x=0;
        int f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9') {
            if (ch=='-') {
                f=-1;
            }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        }
        x*=f;
    }
    
    struct note {
        int l,r;
        int id;
    };
    
    bool operator < (const note &x,const note &y) {
        return x.l<y.l;
    }
    
    note a[N<<1];
    int n,m;
    int fa[N<<1][20];
    int ans[N];
    
    inline int jump(int x,int to_x) {
        int res=0;
        for(int i=19;i+1;i--) {
            if (fa[x][i]&&a[fa[x][i]].r<a[to_x].l+m) {
                res+=(1<<i);
                x=fa[x][i];
            }
        }
        return res+2;
    }
    
    int main() {
        read(n),read(m);
        for(int i=1;i<=n;i++) {
            read(a[i].l),read(a[i].r);
            if (a[i].r<a[i].l) {
                a[i].r+=m;
            }
            a[i+n].l=a[i].l+m;
            a[i+n].r=a[i].r+m;
            a[i].id=i;
        }
        sort(a+1,a+n+n+1);
        for(int i=1;i<=n+n;i++) {
            int l=i+1,r=n+n;
            while(l<r) {
                int mid=(l+r+1)>>1;
                if (a[mid].l<=a[i].r) {
                    l=mid;
                } else {
                    r=mid-1;
                }
            }
            if (l!=n+n+1) {
                fa[i][0]=l;
            }
        }
        for(int i=1;i<=19;i++) {
            for(int j=1;j<=n*2;j++) {
                fa[j][i]=fa[fa[j][i-1]][i-1];
            }
        }
        for(int i=1;i<=n;i++) {
            ans[a[i].id]=jump(i,i);
        }
        for(int i=1;i<=n;i++) {
            printf("%d ",ans[i]);
        }
        return 0;
    }
    

    Author: tt66ea

    Created: 2021-08-02 周一 21:19

    Validate

  • 相关阅读:
    python之re(正则表达式)
    virtualbox之下载地址
    数据库之sqlite
    vmware 虚拟机扩展 liunx系统硬盘空间
    常见python面试题-手写代码系列
    Python的Struct模块
    mac上安装brew如何加速
    outlook数字证书导出、导入及解决老是弹出macOS需要访问系统钥匙串弹窗问题
    docker命令学习
    Message from syslogd不停的打日志
  • 原文地址:https://www.cnblogs.com/tt66ea-blog/p/15091781.html
Copyright © 2011-2022 走看看