《P6492 [COCI 2010/2011 #6] STEP》

发布于:2025-06-30 ⋅ 阅读:(14) ⋅ 点赞:(0)

题目描述

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

有 q 次修改,每次给定一个 x,若 ax​ 为 L,则将 ax​ 修改成 R,否则将 ax​ 修改成 L

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

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

输入格式

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

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

输出格式

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

输入输出样例

输入 #1复制

6 2
2
4

输出 #1复制

3
5

输入 #2复制

6 5
4
1
1
2
6

输出 #2复制

3
3
3
5
6

说明/提示

数据规模与约定

对于全部的测试点,保证 1≤n,q≤2×105,1≤x≤n。

说明

题目译自 COCI2010-2011 CONTEST #6 T5 STEP,翻译来自 @一扶苏一

代码实现:

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 200005;

struct SegmentNode {
    int left_val;      // 左端点的值
    int right_val;     // 右端点的值
    int left_max_len;  // 左端连续相同值的最大长度
    int right_max_len; // 右端连续相同值的最大长度
    int max_len;       // 区间内连续相同值的最大长度
    int interval_len;  // 区间长度
};

SegmentNode tree[MAXN << 2];
int n, q; // q代替m表示查询次数

// 合并子节点信息到父节点
void merge(int node) {
    int left_child = node << 1;
    int right_child = node << 1 | 1;
    
    tree[node].left_val = tree[left_child].left_val;
    tree[node].right_val = tree[right_child].right_val;
    
    tree[node].left_max_len = tree[left_child].left_max_len;
    tree[node].right_max_len = tree[right_child].right_max_len;
    
    tree[node].max_len = max(tree[left_child].max_len, tree[right_child].max_len);
    
    if (tree[left_child].right_val != tree[right_child].left_val) {
        tree[node].max_len = max(tree[node].max_len, tree[left_child].right_max_len + tree[right_child].left_max_len);
        
        if (tree[left_child].max_len == tree[left_child].interval_len) {
            tree[node].left_max_len += tree[right_child].left_max_len;
        }
        
        if (tree[right_child].max_len == tree[right_child].interval_len) {
            tree[node].right_max_len += tree[left_child].right_max_len;
        }
    }
}

// 构建线段树
void build(int left, int right, int node) {
    tree[node].interval_len = right - left + 1;
    
    if (left == right) {
        tree[node].left_val = 1;
        tree[node].right_val = 1;
        tree[node].left_max_len = 1;
        tree[node].right_max_len = 1;
        tree[node].max_len = 1;
        return;
    }
    
    int mid = (left + right) / 2;
    build(left, mid, left_child);
    build(mid + 1, right, right_child);
    merge(node);
}

// 单点更新
void update(int pos, int left, int right, int node) {
    if (left == right) {
        tree[node].left_val ^= 1;
        tree[node].right_val = tree[node].left_val;
        return;
    }
    
    int mid = (left + right) / 2;
    if (pos <= mid) update(pos, left, mid, left_child);
    else update(pos, mid + 1, right, right_child);
    
    merge(node);
}

int main() {
    scanf("%d %d", &n, &q);
    build(1, n, 1);
    
    int x;
    while (q--) {
        scanf("%d", &x);
        update(x, 1, n, 1);
        printf("%d\n", max(tree[1].max_len, max(tree[1].left_max_len, tree[1].right_max_len)));
    }
    
    return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到