1. 程式人生 > >【LOJ】#2007. 「SCOI2015」國旗計劃

【LOJ】#2007. 「SCOI2015」國旗計劃

end vector TE ID tchar 路徑 記錄 pla AC

題解

考慮樸素的做法,斷環為鏈,復制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; }

【LOJ】#2007. 「SCOI2015」國旗計劃