zoukankan      html  css  js  c++  java
  • hdu 1540 Tunnel Warfare 线段树

    给你一个01序列,每次将一个位置变成0或1。问某个位置所在的最长1串多长。

    我们维护vec[k],k所代表序列中的最长子串长度,ls[k],k所代表序列中的最长前缀,rs[k],k所代表序列中的最长后缀。

    合并很简单,vec[k] = max(vec[k << 1],vec[k << 1 | 1],rs[k <<1] + ls[k << 1 | 1]。ls[k] = ls[k << 1] (左半段不都是1) ls[k] = vec[k << 1] +  ls[k << 1 | 1](左半段都是1) rs维护同理。

    然后考虑查询,最后查询位置所在的最长1串,必定是某个区间的rs和相邻区间的ls拼接起来的。

    我们每次看,如果x属于左半段的最大后缀,那么这个最大后缀+右半段最大前缀就是答案。否则递归左子树去找。(x属于左半段)

    如果x属于右半段的最大前缀,那么这个最大后缀+右半段最大前缀就是答案。否则递归右子树去找。(x属于右半段)

    这题多case,题目没说.....

     1 #include <cstdio>
     2 #include <stack>
     3 using namespace std;
     4 stack <int> stk;
     5 int vec[210000],ls[210000],rs[210000];
     6 int n,q;
     7 void updata(int k,int l,int r)
     8 {
     9     int mid = l + r >> 1;
    10     if (vec[k << 1] == mid - l + 1)
    11         ls[k] = vec[k << 1] + ls[k << 1 | 1];
    12     else
    13         ls[k] = ls[k << 1];
    14     if (vec[k << 1 | 1] == r - mid)
    15         rs[k] = vec[k << 1 | 1] + rs[k << 1];
    16     else
    17         rs[k] = rs[k << 1 | 1];
    18     vec[k] = max(rs[k << 1] + ls[k << 1 | 1],max(vec[k << 1],vec[k << 1 | 1]));
    19 }
    20 void build(int k,int l,int r)
    21 {
    22     if (l == r)
    23     {
    24         vec[k] = ls[k] = rs[k] = 1;
    25         return;
    26     }
    27     int mid = l + r >> 1;
    28     build(k << 1,l,mid);
    29     build(k << 1 | 1,mid + 1,r);
    30     updata(k,l,r);
    31 }
    32 void change(int k,int l,int r,int x,int vl)
    33 {
    34     if (l == r)
    35     {
    36         vec[k] = ls[k] = rs[k] = vl;
    37         return;
    38     }
    39     int mid = l + r >> 1;
    40     if (x <= mid) change(k << 1,l,mid,x,vl);
    41     if (x >= mid + 1) change(k << 1 | 1,mid + 1,r,x,vl);
    42     updata(k,l,r);
    43 }
    44 int query(int k,int l,int r,int x)
    45 {
    46     if (l == r)
    47         return vec[k];
    48     int mid = l + r >> 1;
    49     if (x <= mid)
    50     {
    51         if (x >= (mid - rs[k << 1] + 1))
    52             return rs[k << 1] + ls[k << 1 | 1];
    53         else
    54             return query(k << 1,l,mid,x);
    55     }else
    56     {
    57         if (x <= (mid + ls[k << 1 | 1]))
    58             return rs[k << 1] + ls[k << 1 | 1];
    59         else
    60             return query(k << 1 | 1,mid + 1,r,x);
    61     }
    62 }
    63 int main()
    64 {
    65     while (scanf("%d%d",&n,&q) > 0)
    66     {
    67         build(1,1,n);
    68         char str[10];
    69         int tx;
    70         for (int i = 1;i <= q;i++)
    71         {
    72             scanf("%s",str);
    73             if (str[0] == 'D')
    74             {
    75                 scanf("%d",&tx);
    76                 change(1,1,n,tx,0);
    77                 stk.push(tx);
    78             }else if (str[0] == 'Q')
    79             {
    80                 scanf("%d",&tx);
    81                 printf("%d
    ",query(1,1,n,tx));
    82             }else
    83             {
    84                 change(1,1,n,stk.top(),1);
    85                 stk.pop();
    86             }
    87         }
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    OLT配置学习
    notepad配合正则表达式处理文本
    利用expect和sshpass完美非交互性执行远端命令
    yum 数据库报错与重构
    杀死dialog
    OLT配置说明
    freeradius下发限速信息字段
    debug调试日志和数据查询
    通过windows的超级终端连接华为交换机
    强制清除交换机端口所有配置
  • 原文地址:https://www.cnblogs.com/iat14/p/12189511.html
Copyright © 2011-2022 走看看