zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    统计字符串中每个字母出现的次数
    三次握手和四次挥手
    select后面不能包含group by 后面没有的列
    常用adb命令
    replace和replaceAll的区别
    java统计一个字符串中某个字串出现的次数
    大厂如何解决分布式事务
    ADB 用法大全
    PBN飞越转弯Flyover衔接TF、CF航段保护区组图
    PBN旁切转弯保护区组图
  • 原文地址:https://www.cnblogs.com/Griselda/p/3119182.html
Copyright © 2011-2022 走看看