HDOJ1540 - Tunnel Warfare 线段树区间合并
生活随笔
收集整理的這篇文章主要介紹了
HDOJ1540 - Tunnel Warfare 线段树区间合并
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
HDOJ 1540
題目大意:給定兩個整數N,M, 其中N表示一共有N個村莊,M代表有M次操作,操作有以下:
1.??? D x? 銷毀村莊x
2.??? Q x? 詢問與村莊x相鄰的村莊總數
3.??? R???? 最近一次銷毀的村莊得到重建
?
問題分析:
對于N個村莊,可以建立一顆線段樹,維護最大連續區間長度,操作分析:
?
具體實現:
對于有N個村莊,可以建立區間為[1, N]的線段樹,維護最大連續區間長度,節點里有這些信息需要維護:最大左連續區間長度,最大右連續區間長度,總對大連續區間長度,覆蓋標志,每次PushUp都要將左右子區間進行合并,加入lazy-tag優化時間復雜度(簡單來說就是將更新延遲到下一次詢問或者需要更新的時候),對于R操作,因為該操作的對象是最近一次銷毀的村莊,因此在每一次 D x 操作以后就將 x 進棧,等到 R 操作時就將棧頂彈出,于是操作對象就轉移到棧頂元素
?
代碼:
1 #include <stack> 2 #include <cstdio> 3 using namespace std; 4 5 #define lson l, m, rt<<1 6 #define rson m+1, r, rt<<1|1 7 8 const int maxn = 50000; 9 10 char cmd[5]; 11 stack <int> st; 12 int n, mNum, a; 13 int lsum[maxn*3], rsum[maxn*3], sum[maxn*3], cover[maxn*3]; 14 15 int Max(int x, int y) 16 { 17 return (x>y ? x:y); 18 }/* Max */ 19 20 void BuildTree(int l, int r, int rt) 21 { 22 cover[rt] = -1; 23 lsum[rt] = rsum[rt] = sum[rt] = r-l+1; 24 25 if (l == r) 26 return ; 27 28 int m = (l+r)>>1; 29 BuildTree(lson); 30 BuildTree(rson); 31 }/* BuildTree */ 32 33 void PushDown(int rt, int k) 34 { 35 if (cover[rt] != -1) 36 { 37 cover[rt<<1] = cover[rt<<1|1] = cover[rt]; 38 lsum[rt<<1] = rsum[rt<<1] = sum[rt<<1] = cover[rt] ? 0:k-(k>>1); 39 lsum[rt<<1|1] = rsum[rt<<1|1] = sum[rt<<1|1] = cover[rt] ? 0:(k>>1); 40 cover[rt] = -1; 41 } 42 }/* PushDown */ 43 44 int Query(int p, int l, int r, int rt) 45 { 46 if (sum[rt]==0 || sum[rt]==r-l+1 || l==r) 47 return sum[rt]; 48 49 PushDown(rt, r-l+1); 50 51 int m = (l+r)>>1; 52 if (p <= m) 53 { 54 if (p > m-rsum[rt<<1]) 55 return rsum[rt<<1]+Query(m+1, rson); 56 else 57 return Query(p, lson); 58 } 59 else 60 { 61 if (p <= m+lsum[rt<<1|1]) 62 return lsum[rt<<1|1]+Query(m, lson); 63 else 64 return Query(p, rson); 65 } 66 }/* Query */ 67 68 void PushUp(int rt, int k) 69 { /* 左右子區間合并 */ 70 lsum[rt] = lsum[rt<<1]; 71 rsum[rt] = rsum[rt<<1|1]; 72 73 if (lsum[rt] == k-(k>>1)) 74 lsum[rt] += lsum[rt<<1|1]; 75 if (rsum[rt] == (k>>1)) 76 rsum[rt] += rsum[rt<<1]; 77 78 sum[rt] = Max(rsum[rt<<1]+lsum[rt<<1|1], Max(sum[rt<<1], sum[rt<<1|1])); 79 }/* PushUp */ 80 81 void UpData(int p, int c, int l, int r, int rt) 82 { 83 if (l == r) 84 { 85 lsum[rt] = rsum[rt] = sum[rt] = c ? 0:r-l+1; 86 cover[rt] = c; 87 88 return ; 89 }/* End of If */ 90 91 PushDown(rt, r-l+1); 92 93 int m = (l+r)>>1; 94 if (p <= m) 95 UpData(p, c, lson); 96 else 97 UpData(p, c, rson); 98 99 PushUp(rt, r-l+1); 100 }/* UpData */ 101 102 int main() 103 { 104 while (~scanf("%d %d", &n, &mNum)) 105 { 106 BuildTree(1, n, 1); 107 108 while (!st.empty()) 109 st.pop(); 110 111 for (int i=1; i<=mNum; ++i) 112 { 113 scanf("%s", cmd); 114 if (cmd[0] == 'Q') 115 { 116 scanf("%d", &a); 117 printf("%d\n", Query(a, 1, n, 1)); 118 } 119 else if (cmd[0] == 'D') 120 { 121 scanf("%d", &a); 122 UpData(a, 1, 1, n, 1); 123 st.push(a); 124 } 125 else 126 { 127 a = st.top(); 128 st.pop(); 129 UpData(a, 0, 1, n, 1); 130 } 131 }/* End of For */ 132 }/* End of While */ 133 134 return 0; 135 }?
轉載于:https://www.cnblogs.com/yewei/archive/2012/05/10/2494324.html
總結
以上是生活随笔為你收集整理的HDOJ1540 - Tunnel Warfare 线段树区间合并的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 创建库设置中文
- 下一篇: 《PHP和MySQL Web开发》学习之