Tunnel Warfare(HDU1540+线段树+区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540
题目:
题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的村庄相连接的城市数量。
思路:线段树+区间合并。
代码实现如下:
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <stack> 5 #include <cmath> 6 #include <bitset> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 typedef long long ll; 17 typedef unsigned long long ull; 18 19 #define lson i<<1,l,mid 20 #define rson i<<1|1,mid+1,r 21 #define bug printf("*********\n"); 22 #define FIN freopen("D://code//in.txt", "r", stdin); 23 #define debug(x) cout<<"["<<x<<"]" <<endl; 24 #define IO ios::sync_with_stdio(false),cin.tie(0); 25 26 const double eps = 1e-8; 27 const int mod = 1e8; 28 const int maxn = 5e4 + 7; 29 const double pi = acos(-1); 30 const int inf = 0x3f3f3f3f; 31 const ll INF = 0x3f3f3f3f3f3f3f3f; 32 33 inline int read() {//读入挂 34 int ret = 0, c, f = 1; 35 for(c = getchar(); !(isdigit(c) || c == '-'); c = getchar()); 36 if(c == '-') f = -1, c = getchar(); 37 for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0'; 38 if(f < 0) ret = -ret; 39 return ret; 40 } 41 42 int n, q, x, t; 43 char op[5]; 44 int tack[maxn]; 45 46 struct node { 47 int l, r, mx, ls, rs; //ls为左端最大连续区间,rs为右端最大连续区间,mx为区间内最大连续区间 48 }segtree[maxn*4]; 49 50 void build(int i, int l, int r) { 51 segtree[i].l = l, segtree[i].r = r; 52 segtree[i].mx = segtree[i].ls = segtree[i].rs = r - l + 1; 53 if(l == r) return; 54 int mid = (l + r) >> 1; 55 build(lson); 56 build(rson); 57 } 58 59 void update(int i, int pos, int x) { 60 if(segtree[i].l == segtree[i].r) { 61 if(x == 1) segtree[i].mx = segtree[i].ls = segtree[i].rs = 1; //此处为修复操作 62 else segtree[i].mx = segtree[i].ls = segtree[i].rs = 0; //摧毁操作 63 return; 64 } 65 int mid = (segtree[i].l + segtree[i].r) >> 1; 66 if(pos <= mid) { 67 update(i * 2, pos, x); 68 } else { 69 update(i * 2 + 1, pos, x); 70 } 71 segtree[i].ls = segtree[i*2].ls; 72 segtree[i].rs = segtree[i*2+1].rs; 73 segtree[i].mx = max(max(segtree[i*2].mx, segtree[i*2+1].mx), segtree[2*i].rs + segtree[i*2+1].ls); 74 if(segtree[i*2].ls == segtree[i*2].r - segtree[i*2].l + 1) { //如果左端全是连接的,那么ls还要右子树的ls 75 segtree[i].ls += segtree[i*2+1].ls; 76 } 77 if(segtree[i*2+1].rs == segtree[i*2+1].r - segtree[i*2+1].l + 1) { //同理 78 segtree[i].rs += segtree[i*2].rs; 79 } 80 } 81 82 int query(int i, int pos) { 83 if(segtree[i].l == segtree[i].r || segtree[i].mx == segtree[i].r - segtree[i].l + 1 || segtree[i].mx == 0) { 84 return segtree[i].mx; 85 } 86 int mid = (segtree[i].l + segtree[i].r) >> 1; 87 if(pos <= mid) { 88 if(pos >= segtree[2*i].r - segtree[i*2].rs + 1) { //如果pos与右边连接,那么还需要跑另一棵子树 89 return query(i * 2, pos) + query(i * 2 + 1, mid + 1); 90 } else { 91 return query(i * 2, pos); 92 } 93 } else { 94 if(pos <= segtree[i * 2 + 1].l + segtree[i*2+1].ls - 1) { //同理 95 return query(i * 2 + 1, pos) + query(i * 2, mid); 96 } else { 97 return query(i * 2 + 1, pos); 98 } 99 } 100 } 101 102 int main() { 103 //FIN; 104 while(~scanf("%d%d", &n, &q)) { 105 build(1, 1, n); 106 t = 0; 107 while(q--) { 108 scanf("%s", op); 109 if(op[0] == 'D') { 110 scanf("%d", &x); 111 tack[++t] = x; 112 update(1, x, 2); 113 } else if(op[0] == 'R') { 114 if(t > 0) { 115 x = tack[t--]; 116 update(1, x, 1); 117 } 118 } else { 119 scanf("%d", &x); 120 printf("%d\n", query(1, x)); 121 } 122 } 123 } 124 return 0; 125 }
版权声明:本文允许转载,转载时请注明原博客链接,谢谢~