1. 程式人生 > >4444: [Scoi2015]國旗計劃

4444: [Scoi2015]國旗計劃

mat getchar second %d using 下一個 printf truct math

4444: [Scoi2015]國旗計劃

Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 485 Solved: 232

Description

A國正在開展一項偉大的計劃——國旗計劃。這項計劃的內容是邊防戰士手舉國旗環繞邊境線奔襲一圈。這 項計劃需要多名邊防戰士以接力的形式共同完成,為此,國土安全局已經挑選了N名優秀的邊防戰上作為這 項計劃的候選人。 A國幅員遼闊,邊境線上設有M個邊防站,順時針編號1至M。每名邊防戰士常駐兩個邊防站,並且善於 在這兩個邊防站之間長途奔襲,我們稱這兩個邊防站之間的路程是這個邊防戰士的奔襲區間。n名邊防戰士 都是精心挑選的,身體素質極佳,所以每名邊防戰士的奔襲區間都不會被其他邊防戰士的奔襲區間所包含。 現在,國十安全局局長希望知道,至少需要多少名邊防戰士,才能使得他們的奔襲區間覆蓋全部的邊境線, 從而順利地完成國旗計劃。不僅如此,安全局局長還希望知道更詳細的信息:對於每一名邊防戰士,在他必 須參加國旗計劃的前提下,至少需要多少名邊防戰士才能覆蓋全部邊境線,從而順利地完成國旗計劃。

Input

第1行,包含2個正整數N,M,分別表示邊防戰士數量和邊防站數量。 隨後n行,每行包含2個正整數。其中第i行包含的兩個正整數Ci、Di分別表示i號邊防戰士常駐的兩個邊防站編號, Ci號邊防站沿順時針方向至Di號邊防站力他的奔襲區間。數據保證整個邊境線都是可被覆蓋的。

Output

輸出數據僅1行,需要包含n個正整數。其中,第j個正整數表示j號邊防戰士必須參加的前提下至少需要 多少名邊防戰士才能順利地完成國旗計劃

Sample Input

4 8
2 5
4 7
6 1
7 3

Sample Output

3 3 4 3

HINT

n≤2×10^5,M< 10^9,1≤Ci,Di≤M

分析

每一個區間都不能被其他區間所包含,也就是如果li<lj那麽一定滿足ri<rj,然後就可以貪心一下。

對於區間[l,r],可以在區間找到一個li,使得這個li的右端點ri最大,然後繼續尋找。

這樣可以按照左端點排序,然後每一個戰士要找的下一個戰士都是確定的。這樣預處理出來。

求解有多少戰士的話,可以用倍增,f[i][j]表示從i點走2j步到達的點,如果f[i][j]所到達的點沒有超出m,就可以從i點走2j

步,到達下一個點。 繼續尋找。

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<set>
 5 
 6 using namespace std;
 7 
 8 const int MAXN = 400100;
 9 const int INF = 0x7fffffff;
10 
11 struct Peo{
12     int l,r,id;
13     bool operator < (const Peo &a) const
14     {
15         return l < a.l;
16     }
17 }p[MAXN];
18 
19 int f[MAXN][30],ans[MAXN];//f[i][j]表示從i點走2^j步到達的點 
20 int tot,n,m;
21 set< pair<int,int> >s;
22 
23 int read()
24 {
25     int x = 0,f = 1;char ch = getchar();
26     while (ch<0||ch>9) {if (ch==-) f=-1;ch = getchar(); }
27     while (ch>=0&&ch<=9){x = x*10+ch-0;ch = getchar(); }
28     return x*f;
29 }
30 
31 void work(int x)
32 {
33     int d = p[x].id, L = p[x].l+m;
34     for (int i=20; i>=0; --i)
35         if (f[x][i])
36             if (p[f[x][i]].r<L) 
37                 x = f[x][i],ans[d] += (1<<i);
38 }
39 
40 int main()
41 {
42     n = read(),m = read();
43     for (int x,y,i=1; i<=n; ++i)
44     {
45         x = read();y = read();
46         if (y<x) y += m;
47         p[++tot].l = x; p[tot].r = y; p[tot].id = i;
48         p[++tot].l = x+m;p[tot].r = y+m;    
49     }
50     
51     sort(p+1,p+tot+1);
52     s.insert(make_pair(p[tot].l,tot));
53     for (int i=tot-1; i; --i)
54     {
55         f[i][0] = (--s.upper_bound(make_pair(p[i].r,INF)))->second; 
56         s.insert(make_pair(p[i].l,i));
57     }
58     
59     for (int i=1; i<=20; ++i)
60         for (int j=tot; j; --j)
61             f[j][i] = f[f[j][i-1]][i-1];
62     for (int i=1; i<=tot; ++i)
63         if (p[i].id) work(i);
64         
65     for (int i=1; i<=n; ++i)
66          printf("%d ",ans[i]+2);
67     return 0;
68 }

4444: [Scoi2015]國旗計劃