• 【题解】【神奇校内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

  • 相关阅读:
    只要7步,就能将任何魔方6面还原
    写一篇文章测试一下
    关于80端口被占用
    打造只能输入数字的文本框
    windows下MySql忘记密码的解决方案
    linq to xml 操作sitemap
    C#设计模式——工厂方法模式(Factory Method Pattern)
    C#设计模式——单件模式(Singleton Pattern)
    C#设计模式——迭代器模式(Iterator Pattern)
    C#设计模式——状态模式(State Pattern)
  • 原文地址:https://www.cnblogs.com/tt66ea-blog/p/15091781.html
Copyright © 2020-2023  润新知