P6492 [COCI2010-2011#6] STEP(线段树)

P6492 [COCI2010-2011#6] STEP(线段树)

题目描述

给定一个长度为 n 的字符序列 a,初始时序列中全部都是字符 L

q 次修改,每次给定一个 x,若 (a_x)L,则将 (a_x) 修改成 R,否则将 (a_x) 修改成 L

对于一个只含字符 LR 的字符串 s,若其中不存在连续的 LR,则称 s 满足要求。

每次修改后,请输出当前序列 a 中最长的满足要求的连续子串的长度。

输入格式

第一行有两个整数,分别表示序列的长度 n 和修改操作的次数 q

接下来 q 行,每行一个整数,表示本次修改的位置 x

输出格式

对于每次修改操作,输出一行一个整数表示修改 a 中最长的满足要求的子串的长度。

分析

和维护最大子段和一样,线段树维护4个值:节点向左向右最远能拓展多少、节点的和、节点的答案,在pushup的时候更新即可。

const int N = 2e5+10;
int n,q,a[N];
struct seg{
  int l, r, lmx, rmx, sum, ans;
  inline int mid() {
    return (l+r) >> 1;
  }
}node[N<<2];

void up(int i) {
  node[i].sum = node[ls].sum + node[rs].sum;
  node[i].ans = max(node[ls].ans, node[rs].ans);
  node[i].lmx = node[ls].lmx;
  node[i].rmx = node[rs].rmx;
  if (a[node[ls].r] != a[node[rs].l]) {
    node[i].ans = max(node[i].ans, node[ls].rmx + node[rs].lmx);
    if (node[ls].lmx == node[ls].sum) {
      node[i].ans = max(node[i].ans, node[ls].lmx + node[rs].lmx);
      node[i].lmx = max(node[i].lmx, node[ls].lmx + node[rs].lmx);
    }
    if (node[rs].rmx == node[rs].sum) {
      node[i].ans = max(node[i].ans, node[ls].rmx + node[rs].rmx);
      node[i].rmx = max(node[i].rmx, node[rs].rmx + node[ls].rmx);
    }
  }
}

void build(int l, int r , int i) {
  node[i].l = l, node[i].r = r;
  if (l == r) {
    node[i].lmx = node[i].rmx = node[i].sum = 1;
    return;
  }
  int mid = (l+r) >> 1;
  build(l,mid,ls);
  build(mid+1,r,rs);
  up(i);
}

void modify(int p, int i) {
  if (node[i].l == p && p == node[i].r) {
    a[p] ^= 1;
    return;
  }
  int mid = node[i].mid();
  if (p <= mid) modify(p,ls);
  else modify(p,rs);
  up(i);
}

void run() {
  n = rd(), q = rd();
  build(1,n,1);
  rep(i,1,q) {
    int p = rd();
    modify(p,1);
    pnt(node[1].ans);
  }
}
原文地址:https://www.cnblogs.com/hznudreamer/p/13765288.html