Bzoj[Usaco2018 Feb]5194 Snow Boots(線段樹)

Descriptionc++

到冬天了,這意味着下雪了!從農舍到牛棚的路上有N塊地磚,方便起見編號爲1…N,第i塊地磚上積了fi英尺的雪
。在Farmer John的農舍的地窖中,總共有B雙靴子,編號爲1…B。其中某些比另外一些結實,某些比另外一些輕便。具
體地說,第i雙靴子可以讓FJ在至多si英尺深的積雪中行走,可以讓FJ每步至多前進di。Farmer John從1號地磚出
發,他必須到達N號地磚才能叫醒奶牛們。1號地磚在農舍的屋檐下,N號地磚在牛棚的屋檐下,因此這兩塊地磚都
沒有積雪。幫助Farmer John求出哪些靴子能夠幫助他走完這段艱辛的路程。

Input

第一行包含兩個空格分隔的整數N和B(1≤N,B≤10^5)。git

第二行包含N個空格分隔的整數;第i個整數爲fi,即i號地磚的積雪深度(0≤fi≤10^9)。輸入保證f1=fN=0
下面B行,每行包含兩個空格分隔的整數。第i+2行的第一個數爲si,表示第i雙靴子可以承受的最大積雪深度。
第i+2行的第二個數爲di,表示第i雙靴子的最大步長。輸入保證0≤si≤10^9以及1≤di≤N-1

Output

輸出包含N行ui

第i行包含一個整數:若是Farmer John可以穿着第i雙靴子從1號地磚走到N號地磚,爲1,不然爲0

Sample Input

8 7
0 3 8 5 6 9 0 0
0 5
0 6
6 2
8 1
10 1
5 3
150 7

Sample Output

0
1
1
0
1
1
1
---------------------------------------------------------分割線-------------------------------------------------------------
題意:
給定一個長度爲n的序列。有m次詢問,每次詢問給定兩個數sidi一開始站在0這個位置,
每次你能夠走不超過di的距離,但你到達的位置的數不能超過si,問可否走到n+1
 

這題的解法好像挺多,好比並查集?可是我仍是用線段樹了,由於講師是這麼講的23333
思考對問題模型作一些轉化,假如說有連續的長度爲di的距離都大於si,那麼顯然你是不管如何都不能走過去
不然顯然你是不管如何都可以走過去的
這樣問題就變成了考慮一個長度爲n的序列中,最長的連續的不能通行的長度是多少。
可是這個東西對於m次詢問咱們顯然是不能暴力去搞的,這樣確定會T.
那麼考慮一下咱們是否能夠把si的順序調一下而後很方便的去搞。
由於咱們很容易想到一個貪心就是若是咱們將si按照從大到小排序時,咱們每次只須要在原來的基礎上刪掉一些選擇要走的磚便可
反之如果從小到大排,就是加上一些選擇要走的磚
而若是咱們再把磚的大小排一下序,那麼在進行處理時咱們插入磚的順序就也是單調的了,這樣遍歷一遍複雜度O(n)
那麼下面的問題就是處理插入或是刪除以維護序列最長的不能通行的長度了
因而咱們能夠想到利用線段樹維護這個信息,而後將si和序列從大到小或是從小到大排序,這樣總複雜度是O((n+m)logn)
具體操做能夠看看代碼 
 
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define uint unsigned int
 4 #define ull unsigned long long
 5 using namespace std;  6 const int maxn = 100010;  7 struct enkidu {  8     int di, si, id;  9 }ask[maxn], a[maxn]; 10 struct shiki { 11     int l, r, l_lin, r_lin; 12     int max_cnt; 13 }tree[maxn << 2]; 14 //l_lin表示這個區間從左邊開始連續的不能走的長度 15 //r_lin表示這個區間從右邊開始連續的不能走的長度 
16 int n, m; 17 int ans[maxn]; 18 
19 inline int read() { 20     int x = 0, y = 1; 21     char ch = getchar(); 22     while(!isdigit(ch)) { 23         if(ch == '-') y = -1; 24         ch = getchar(); 25  } 26     while(isdigit(ch)) { 27         x = (x << 1) + (x << 3) + ch - '0'; 28         ch = getchar(); 29  } 30     return x * y; 31 } 32 
33 inline bool cmp(enkidu a, enkidu b) { 34     return a.si < b.si; 35 } 36 
37 inline void maintain(int pos) { 38     int ls = pos << 1, rs = pos << 1 | 1; 39     if(tree[ls].r - tree[ls].l + 1 == tree[ls].max_cnt) 40         tree[pos].l_lin = tree[ls].max_cnt + tree[rs].l_lin; 41     else tree[pos].l_lin = tree[ls].l_lin; 42     if(tree[rs].r - tree[rs].l + 1 == tree[rs].max_cnt) 43         tree[pos].r_lin = tree[ls].r_lin + tree[rs].max_cnt; 44     else tree[pos].r_lin = tree[rs].r_lin; 45     tree[pos].max_cnt = max(tree[ls].max_cnt, tree[rs].max_cnt); 46     tree[pos].max_cnt = max(tree[pos].max_cnt, tree[ls].r_lin + tree[rs].l_lin); 47 } 48 
49 void build(int pos, int l, int r) { 50     tree[pos].l = l, tree[pos].r = r; 51     if(l == r) { 52         tree[pos].l_lin = tree[pos].r_lin = tree[pos].max_cnt = 1; 53         return; 54  } 55     int  mid = l + r >> 1; 56     build(pos << 1, l, mid); 57     build(pos << 1 | 1, mid + 1, r); 58     maintain-(pos); 59 } 60 
61 void update(int pos, int aim, int l, int r) { 62     if(l == r && l == aim) { 63         tree[pos].max_cnt = tree[pos].l_lin = tree[pos].r_lin = 0; 64         return; 65  } 66     int mid = l + r >> 1; 67     if(aim <= mid) update(pos << 1, aim, l, mid); 68     else update(pos << 1 | 1, aim, mid + 1, r); 69  maintain(pos); 70 } 71 
72 int main() { 73     n = read(), m = read(); 74     for(int i = 1; i <= n; ++i) { 75         a[i].si = read(); 76         a[i].id = i; 77  } 78     for(int i = 1; i <= m; ++i) { 79         ask[i].si = read(), ask[i].di = read(); 80         ask[i].id = i; 81  } 82     sort(ask + 1, ask + m + 1, cmp); 83     sort(a + 1, a + n + 1, cmp); 84     build(1, 1, n); 85     int brick = 0;//磚,表示第幾塊磚
86     for(int i = 1; i <= m; ++i) { 87         while(brick < n && a[brick + 1].si <= ask[i].si) {//若是能夠走 
88             brick++; 89             update(1, a[brick].id, 1, n); 90  } 91         if(tree[1].max_cnt < ask[i].di) ans[ask[i].id] = 1; 92  } 93     for(int i = 1; i <= m; ++i) printf("%d\n", ans[i]); 94     return 0; 95 }
相關文章
相關標籤/搜索