P6492 题解
P6492 [COCI2010-2011#6] STEP - 洛谷
题目大意:维护一段 01 串,支持单点修改,每次修改后求最长的「
下文把 「
考虑用线段树进行维护。我们用
则合并时:
。- 如果
则区间可以合并, ;否则 。 - 如果
等于区间长度且合法区间可以合并,则 ,否则 。 同理。
更新时只反转
#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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步