【LOJ】#2007. 「SCOI2015」国旗计划

题解

考虑朴素的做法,断环为链,复制2M个,找到一个位置i,f(i)是这个位置之前开始的线段,结束位置最远的位置在哪

然后对于每一个人,从自己线段的起点往下跳,跳到起点+M或以后的步数就是答案

我们发现这其实是最后一个点为根构建成的一棵树,很显然的,我们答案只可能是最少的用人数量+1或最少的用人数量
我们遍历整个树,只对第一次遍历到的起点求值,然后剩下的只要特判一下那种情况就好,用一个栈记录一下根节点到它的路径

代码

#include <bits/stdc++.h>
#define MAXN 200005
//#define ivorysi
#define enter putchar('\n')
#define space putchar(' ')
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {putchar('-');x = -x;}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,M,ans;
int num[MAXN * 4],tot,st[MAXN * 4],Cnt,sta[MAXN * 4],top,MK[MAXN],vis[MAXN * 4];
pii seg[MAXN * 2];
vector<int> son[MAXN * 4];
void dfs(int u) {
    sta[++top] = u;
    vis[u] = 1;
    if(st[u]) {
    if(!ans) {
        for(int i = top - 1 ; i >= 1 ; --i) {
        ++ans;
        if(num[sta[i]] >= num[u] + M) break;
        }
        MK[st[u]] = ans;
    }
    else {
        if(top > (ans - 1) && num[sta[top - (ans - 1)]] >= num[u] + M) MK[st[u]] = ans - 1;
        else if(top > ans && num[sta[top - ans]] >= num[u] + M) MK[st[u]] = ans;
        else MK[st[u]] = ans + 1;
    }
    }
    for(auto k : son[u]) {
    dfs(k);
    }
    --top;
}
void Init() {
    read(N);read(M);
    Cnt = N;
    for(int i = 1 ; i <= N ; ++i) {
    read(seg[i].fi);read(seg[i].se);
    if(seg[i].se < seg[i].fi) seg[i].se += M;
    seg[++Cnt] = mp(seg[i].fi + M,seg[i].se + M);
    }
    for(int i = 1 ; i <= Cnt ; ++i) num[++tot] = seg[i].fi,num[++tot] = seg[i].se;
    sort(num + 1,num + tot + 1);
    tot = unique(num + 1,num + tot + 1) - num - 1;
    for(int i = 1 ; i <= N ; ++i) {
    int t = lower_bound(num + 1,num + tot + 1,seg[i].fi) - num;
    st[t] = i;
    }
    sort(seg + 1,seg + Cnt + 1);
    int maxx = 0,p = 1;
    for(int i = 1 ; i <= tot ; ++i) {
    while(p <= Cnt && seg[p].fi <= num[i]) {
        maxx = max(maxx,(int)(lower_bound(num + 1,num + tot + 1,seg[p].se) - num));
        ++p;
    }
    if(maxx != i) son[maxx].pb(i);
    }
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    for(int i = tot ; i >= 1 ; --i) {
    if(!vis[i]) dfs(i);
    }
    for(int i = 1 ; i <= N ; ++i) {
    out(MK[i]);if(i == N) enter;else space;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ivorysi/p/9154405.html