Hdu 1540 【线段树区间合并】.cpp

题意:
  有3个操作
    D a 毁坏某一个点a
    R 修复上一次破坏的点
    Q a 问a点附近连续的点有几个

思路:
  区间合并类的线段树
    结构体表示 {
      l:节点的左界限
      r:节点的右界限
      ll:左起连续的点数
      rr:右起连续的点数
      mm:整个范围内连续最长的点数
    }

Tips:
   主要是更新那一块要考虑父节点可能是由左右节点边界合并的
   询问那一块要考虑是否可以和兄弟节点合并

Code:

 1 #include <stdio.h>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int MAXN = 50010;
 7 
 8 struct Node
 9 {
10     int l, r;
11     int ll, rr, mm;
12 }node[MAXN<<2];
13 
14 void build(int rt, int l, int r)
15 {
16     node[rt].l = l, node[rt].r = r;
17     node[rt].ll = node[rt].rr = node[rt].mm = r-l+1;
18     if (l == r) return;
19     int mid = (r+l)>>1;
20     build(rt<<1, l, mid);
21     build(rt<<1|1, mid+1, r);
22 }
23 
24 void modify(int rt, int p, int w)
25 {
26     if (node[rt].l == node[rt].r) {
27         if (w == 1) node[rt].ll = node[rt].rr = node[rt].mm = 1;
28         else node[rt].ll = node[rt].rr = node[rt].mm = 0;
29         return;
30     }
31     int mid = (node[rt].l + node[rt].r)>>1;
32     if (p <= mid) modify(rt<<1, p, w);
33     else modify(rt<<1|1, p, w);
34 
35     node[rt].ll = node[rt<<1].ll, node[rt].rr = node[rt<<1|1].rr;
36     if (node[rt<<1].rr == node[rt<<1].r-node[rt<<1].l+1) {
37         node[rt].ll = node[rt<<1].rr + node[rt<<1|1].ll;
38     }
39     if (node[rt<<1|1].rr == node[rt<<1|1].r - node[rt<<1|1].l+1) {
40         node[rt].rr = node[rt<<1|1].rr+node[rt<<1].rr;
41     }
42     node[rt].mm = max(node[rt<<1].mm, node[rt<<1|1].mm);
43     node[rt].mm = max(node[rt].mm, node[rt<<1].rr+node[rt<<1|1].ll);
44 }
45 
46 int query(int rt, int p)
47 {
48     int ans;
49     if (node[rt].l == node[rt].r || node[rt].mm == 0 || node[rt].mm == node[rt].r-node[rt].l+1) {
50         return node[rt].mm;
51     }
52     int mid = (node[rt].l+node[rt].r)>>1;
53     if (p <= mid) {
54         ans = query(rt<<1, p);
55         if (p >= node[rt<<1].r-node[rt<<1].rr+1) //ans += node[rt<<1|1].ll;
56             ans += query(rt<<1|1, mid+1);
57     } else {
58         ans = query(rt<<1|1, p);
59         if (p <= node[rt<<1|1].l+node[rt<<1|1].ll-1) //ans += node[rt<<1].rr;
60             ans += query(rt<<1, mid);
61     }
62     return ans;
63 }
64 
65 int main()
66 {
67    // freopen("in.txt", "r", stdin);
68     int n, m, tmp;
69     int sta[MAXN], tp;
70     char ord[3];
71     while (~scanf("%d %d", &n, &m)) {
72         tp = 0;
73         build(1, 1, n);
74         while (m--) {
75             scanf("%s", ord);
76             if (ord[0] == 'D') {
77                 scanf("%d", &tmp);
78                 sta[tp++] = tmp;
79                 modify(1, tmp, 0);
80             } else if (ord[0] == 'Q') {
81                 scanf("%d", &tmp);
82                 printf("%d\n", query(1, tmp));
83             } else {
84                 tp--;
85                 modify(1, sta[tp], 1);
86             }
87         }
88     }
89     return 0;
90 }
View Code


链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540

原文地址:https://www.cnblogs.com/Griselda/p/3119182.html