日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDOJ1540 - Tunnel Warfare 线段树区间合并

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

HDOJ 1540

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

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

2.??? Q x? 詢問與村莊x相鄰的村莊總數(shù)

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

?

問題分析:

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

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

    具體實現(xiàn):

    對于有N個村莊,可以建立區(qū)間為[1, N]的線段樹,維護最大連續(xù)區(qū)間長度,節(jié)點里有這些信息需要維護:最大左連續(xù)區(qū)間長度,最大右連續(xù)區(qū)間長度,總對大連續(xù)區(qū)間長度,覆蓋標志,每次PushUp都要將左右子區(qū)間進行合并,加入lazy-tag優(yōu)化時間復雜度(簡單來說就是將更新延遲到下一次詢問或者需要更新的時候),對于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 { /* 左右子區(qū)間合并 */ 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 线段树区间合并的全部內容,希望文章能夠幫你解決所遇到的問題。

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