zoukankan      html  css  js  c++  java
  • HDOJ1540 Tunnel Warfare 线段树区间合并

    HDOJ 1540

    题目大意:给定两个整数N,M, 其中N表示一共有N个村庄,M代表有M次操作,操作有以下:

    1.    D x  销毁村庄x

    2.    Q x  询问与村庄x相邻的村庄总数

    3.    R     最近一次销毁的村庄得到重建

    问题分析:

    对于N个村庄,可以建立一颗线段树,维护最大连续区间长度,操作分析:

    1. 在线段树上找到x节点,并将x节点“销毁”(村庄x被销毁),然后分别更新与x节点(村庄x)相关联的节点值(这里指左右连续区间的长度)
    2. 对于询问操作,显然这里要求返回的是存在x的最大左右连续区间长度和
    3. 将村庄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 }
  • 相关阅读:
    js对象的所有方法
    js数组的所有方法
    Scss语法
    new一个对象的过程
    promises的深入学习
    jsonp的原理介绍及Promise封装
    Vue页面缓存和不缓存的方法
    JavaScript数据类型
    JS常用函数原理的实现
    @Autowired注解在抽象类中实效的原因分析
  • 原文地址:https://www.cnblogs.com/yewei/p/2494324.html
Copyright © 2011-2022 走看看