日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

HDOJ1540 - Tunnel Warfare 线段树区间合并

發布時間:2025/7/14 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDOJ1540 - Tunnel Warfare 线段树区间合并 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

HDOJ 1540

題目大意:給定兩個整數N,M, 其中N表示一共有N個村莊,M代表有M次操作,操作有以下:

1.??? D x? 銷毀村莊x

2.??? Q x? 詢問與村莊x相鄰的村莊總數

3.??? R???? 最近一次銷毀的村莊得到重建

?

問題分析:

對于N個村莊,可以建立一顆線段樹,維護最大連續區間長度,操作分析:

  • 在線段樹上找到x節點,并將x節點“銷毀”(村莊x被銷毀),然后分別更新與x節點(村莊x)相關聯的節點值(這里指左右連續區間的長度)
  • 對于詢問操作,顯然這里要求返回的是存在x的最大左右連續區間長度和
  • 將村莊x恢復(具體到重置線段的覆蓋標志),并更新與村莊x相關聯的最大連續區間和
  • ?

    具體實現:

    對于有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 线段树区间合并的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。