zoukankan      html  css  js  c++  java
  • 【LOJ】#2007. 「SCOI2015」国旗计划

    题解

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

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

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

    代码

    #include <bits/stdc++.h>
    #define MAXN 200005
    //#define ivorysi
    #define enter putchar('
    ')
    #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;
    }
    
  • 相关阅读:
    基于S3C2410的VIVI移植
    Android 多媒体
    target连上ubuntu,打adb shell后出现insufficient permissions for device错误
    git 学习
    ubuntu10.04中文乱码问题解决方法
    构建MINI2440开发板Ubuntu开发环境串口配置及使用
    如何解决:Android中 Error generating final archive: Debug Certificate expired on 10/09/18 16:30 的错误
    android Notification 学习
    Android declarestyleable:自定义控件的属性(attr.xml,TypedArray)的使用
    ubuntu 11.04 中的bug 渐显滚动条
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9154405.html
Copyright © 2011-2022 走看看