• (线段树区间合并)UVA 11235


    题意:

    一个数列,多次查询L到R最多连续相同数字的数量。

    分析:

    显然区间合并。不过还就没写了,都有点忘了。

    不过回忆一下,push_down还是写对了。

    不过WA了,后来仔细想一想,光查询光用已经维护的答案还不够,还需要在query的时候再合并一下,才能更新出正确的答案。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <vector>
     6 
     7 
     8 using namespace std;
     9 
    10 const int inf = 0x3f3f3f3f;
    11 const int maxn = 100010;
    12 
    13 struct Node {
    14     int left, right;
    15     int llen, rlen, zlen;
    16     int lval, rval;
    17 } node[maxn << 2];
    18 
    19 
    20 
    21 void push_up(int n) {
    22     node[n].llen = node[n << 1].llen;
    23     node[n].lval = node[n << 1].lval;
    24     node[n].rlen = node[n << 1 | 1].rlen;
    25     node[n].rval = node[n << 1 | 1].rval;
    26     if(node[n << 1].llen == node[n << 1].right - node[n << 1].left + 1 && node[n << 1].rval == node[n << 1 | 1].lval) {
    27         node[n].llen += node[n << 1 | 1].llen;
    28     }
    29     if(node[n << 1 | 1].rlen == node[n << 1 | 1].right - node[n << 1 | 1].left + 1 && node[n << 1].rval == node[n << 1 | 1].lval) {
    30         node[n].rlen +=  node[n << 1].rlen;
    31     }
    32     node[n].zlen = max(node[n << 1].zlen, node[n << 1 | 1].zlen);
    33     if(node[n << 1].rval == node[n << 1 | 1].lval) {
    34         node[n].zlen = max(node[n].zlen, node[n << 1].rlen + node[n << 1 | 1].llen);
    35     }
    36 }
    37 
    38 void build(int n, int left, int right) {
    39     node[n].left = left;
    40     node[n].right = right;
    41     if(left == right) {
    42         scanf("%d", &node[n].lval);
    43         node[n].rval = node[n].lval;
    44         node[n].llen = node[n].rlen = node[n].zlen = 1;
    45         return;
    46     }
    47     int mid = (left + right) >> 1;
    48     build(n << 1, left, mid);
    49     build(n << 1 | 1, mid + 1, right);
    50     push_up(n);
    51 }
    52 
    53 
    54 int query(int n, int left, int right) {
    55     if(node[n].left == left && node[n].right == right) {
    56         return node[n].zlen;
    57     }
    58 //    printf("%d %d
    ", node[n].left, node[n].right);
    59     int mid = (node[n].left + node[n].right) >> 1;
    60     int maxs = -1;
    61     if(mid >= right)maxs = max(maxs, query(n << 1, left, right));
    62     else if(mid < left)maxs = max(maxs, query(n << 1 | 1, left, right));
    63     else {
    64         int s = query(n << 1, left, mid);
    65         int t = query(n << 1 | 1, mid + 1, right);
    66         maxs = max(s, t);
    67         int ls = min(node[n << 1].rlen, mid - left + 1);
    68         int rs = min(node[n << 1 | 1].llen, right - mid);
    69         if(node[n << 1].rval == node[n << 1 | 1].lval) {
    70             maxs = max(maxs, ls + rs);
    71         }
    72     }
    73 //    printf("--%d %d %d
    ", node[n].left, node[n].right, maxs);
    74     return maxs;
    75 }
    76 
    77 int main() {
    78 #ifndef ONLINE_JUDGE
    79 //    freopen("1.in", "r", stdin);
    80 //    freopen("1.out", "w", stdout);
    81 #endif
    82     int n, q;
    83     while(~scanf("%d", &n) && n) {
    84         scanf("%d", &q);
    85         build(1, 1, n);
    86 //        for(int i = 1; i <= 250; i++) {
    87 //            printf("%d %d %d %d %d
    ", node[i].left, node[i].right, node[i].llen, node[i].rlen, node[i].zlen);
    88 //        }
    89         while(q--) {
    90             int l, r;
    91             scanf("%d%d", &l, &r);
    92             printf("%d
    ", query(1, l, r));
    93 //            puts("");
    94         }
    95     }
    96     return 0;
    97 
    98 }
  • 相关阅读:
    P2207 Photo
    P1022 计算器的改良
    P1003 铺地毯
    P3014 [USACO11FEB]牛线Cow Line && 康托展开
    P4180 【模板】严格次小生成树[BJWC2010]
    P2776 [SDOI2007]小组队列
    P2426 删数
    P1948 [USACO08JAN]电话线Telephone Lines
    P1978 集合
    P1564 膜拜
  • 原文地址:https://www.cnblogs.com/tak-fate/p/6965364.html
Copyright © 2020-2023  润新知