Out on my own.|

园龄:粉丝:关注:

2024-04-22 14:11阅读: 35评论: 0推荐: 0

P6492 题解

P6492 [COCI2010-2011#6] STEP - 洛谷

题目大意:维护一段 01 串,支持单点修改,每次修改后求最长的「01010101」 的长度。

下文把 「01010101」称为「合法区间」,k 为区间 [l,r] 编号,lk,rk[l,r] 左右子区间编号。

考虑用线段树进行维护。我们用 fl(k),fr(k) 别表示区间 [l,r] 的 01 情况,tl(k),tr(k) 分别表示区间 [l,r]l,r 在内的合法区间的最大长度,t(k) 表示区间 [l,r] 的合法区间的最大长度。

则合并时:

  • fl(k)=fl(lk),fr(k)=fr(rk)
  • 如果 fr(lk)fl(rk) 则区间可以合并,t(k)=max{t(lk),t(rk),tr(lk)+tl(rk)};否则 t(k)=max{t(lk),t(rk)}
  • 如果 tl(k) 等于区间长度且合法区间可以合并,则 tl(k)=tl(lk)=tl(rk),否则 tl(k)=tl(lk)tr(k) 同理。

更新时只反转 fl,fr 即可。时间复杂度 O(nlogn)

#include <iostream>  
#include <cstdio>  
#include <queue>  
using namespace std;  
  
const int N = 200010, N4 = N * 4;  
int n, q;  
int tr[N4], tl[N4], fl[N4], fr[N4], t[N4];  
  
void build(int l, int r, int k) {  
    if(l == r) {  
        fl[k] = fr[k] = 0;  
        t[k] = tl[k] = tr[k] = 1;  
        return;  
    }  
    int mid = (l + r) >> 1, lk = k << 1, rk = lk | 1;  
    build(l, mid, lk); build(mid + 1, r, rk);  
    fl[k] = fl[lk], fr[k] = fr[rk];  
    t[k] = max(t[lk], t[rk]);  
    if(fr[lk] != fl[rk]) t[k] = max(t[k], tl[rk] + tr[lk]);  
    tl[k] = tl[lk], tr[k] = tr[rk];  
    if(tl[lk] == mid - l + 1 && fr[lk] != fl[rk]) tl[k] += tl[rk];  
    if(tr[rk] == r - mid && fr[lk] != fl[rk]) tr[k] += tr[lk];  
}  
  
void upd(int l, int r, int k, int L, int R) {  
    if(L <= l && r <= R) {  
        fl[k] = !fl[k]; fr[k] = !fr[k];  
        return;  
    }  
    int mid = (l + r) >> 1, lk = k << 1, rk = lk | 1;  
    if(L <= mid) upd(l, mid, lk, L, R);  
    if(mid < R) upd(mid + 1, r, rk, L, R);  
    fl[k] = fl[lk], fr[k] = fr[rk];  
    t[k] = max(t[lk], t[rk]);  
    if(fr[lk] != fl[rk]) t[k] = max(t[k], tl[rk] + tr[lk]);  
    tl[k] = tl[lk], tr[k] = tr[rk];  
    if(tl[lk] == mid - l + 1 && fr[lk] != fl[rk]) tl[k] += tl[rk];  
    if(tr[rk] == r - mid && fr[lk] != fl[rk]) tr[k] += tr[lk];  
}  
  
int main() {  
    scanf("%d%d", &n, &q);  
    build(1, n, 1);  
    while(q--){  
        int x; scanf("%d", &x);  
        upd(1, n, 1, x, x);  
        printf("%d\n", t[1]);  
    }  
    return 0;  
}

本文作者:Running-a-way

本文链接:https://www.cnblogs.com/Running-a-way/p/18150553

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Running_a_way  阅读(35)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起