社区讨论
0分求调
P2572[SCOI2010] 序列操作参与者 1已保存回复 0
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mhjdp11b
- 此快照首次捕获于
- 2025/11/04 00:52 4 个月前
- 此快照最后确认于
- 2025/11/04 00:52 4 个月前
CPP
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100005;
struct node {
int l, r, lmax, rmax, smax, sum, lazy, l0max, r0max, s0max;
}tr[N << 2];
int a[N];
inline int ls(int x) {
return x << 1;
}
inline int rs(int x) {
return (x << 1) + 1;
}
inline void pushup(int x) {
int lc = ls(x), rc = rs(x);
tr[x].sum = tr[lc].sum + tr[rc].sum;
tr[x].lmax = tr[lc].lmax;
if (tr[lc].lmax == tr[lc].r - tr[lc].l + 1) {
tr[x].lmax += tr[rc].lmax;
}
tr[x].rmax = tr[rc].rmax;
if (tr[rc].rmax == tr[rc].r - tr[rc].l + 1) {
tr[x].rmax += tr[lc].rmax;
}
tr[x].smax = max(max(tr[lc].smax, tr[rc].smax), tr[lc].rmax + tr[rc].lmax);
tr[x].l0max = tr[lc].l0max;
if (tr[lc].l0max == tr[lc].r - tr[lc].l + 1) {
tr[x].l0max += tr[rc].l0max;
}
tr[x].r0max = tr[rc].r0max;
if (tr[rc].r0max == tr[rc].r - tr[rc].l + 1) {
tr[x].r0max += tr[lc].r0max;
}
tr[x].s0max = max(max(tr[lc].s0max, tr[rc].s0max), tr[lc].r0max + tr[rc].l0max);
}
inline void pushdown(int x) {
if (tr[x].lazy != -1) {
int lc = ls(x), rc = rs(x);
if (tr[x].lazy == 0) {
tr[lc].sum = tr[rc].sum = 0;
tr[lc].lmax = tr[lc].rmax = tr[lc].smax = 0;
tr[rc].lmax = tr[rc].rmax = tr[rc].smax = 0;
tr[lc].l0max = tr[lc].r0max = tr[lc].s0max = tr[lc].r - tr[lc].l + 1;
tr[rc].l0max = tr[rc].r0max = tr[rc].s0max = tr[rc].r - tr[rc].l + 1;
tr[lc].lazy = tr[rc].lazy = 0;
}
else if (tr[x].lazy == 1) {
tr[lc].sum = tr[lc].r - tr[lc].l + 1;
tr[rc].sum = tr[rc].r - tr[rc].l + 1;
tr[lc].lmax = tr[lc].rmax = tr[lc].smax = tr[lc].r - tr[lc].l + 1;
tr[rc].lmax = tr[rc].rmax = tr[rc].smax = tr[rc].r - tr[rc].l + 1;
tr[lc].l0max = tr[lc].r0max = tr[lc].s0max = 0;
tr[rc].l0max = tr[rc].r0max = tr[rc].s0max = 0;
tr[lc].lazy = tr[rc].lazy = 1;
}
else if (tr[x].lazy == 2) {
tr[lc].sum = (tr[lc].r - tr[lc].l + 1) - tr[lc].sum;
tr[rc].sum = (tr[rc].r - tr[rc].l + 1) - tr[rc].sum;
swap(tr[lc].lmax, tr[lc].l0max);
swap(tr[lc].rmax, tr[lc].r0max);
swap(tr[lc].smax, tr[lc].s0max);
swap(tr[rc].lmax, tr[rc].l0max);
swap(tr[rc].rmax, tr[rc].r0max);
swap(tr[rc].smax, tr[rc].s0max);
if (tr[lc].lazy == -1) tr[lc].lazy = 2;
else if (tr[lc].lazy == 2) tr[lc].lazy = -1;
else tr[lc].lazy = 1 - tr[lc].lazy;
if (tr[rc].lazy == -1) tr[rc].lazy = 2;
else if (tr[rc].lazy == 2) tr[rc].lazy = -1;
else tr[rc].lazy = 1 - tr[rc].lazy;
}
tr[x].lazy = -1;
}
}
inline void build(int x, int fl, int fr) {
tr[x].l = fl, tr[x].r = fr, tr[x].lazy = -1;
if (fl == fr) {
tr[x].lmax = tr[x].rmax = tr[x].smax = tr[x].sum = a[fl];
tr[x].l0max = tr[x].r0max = tr[x].s0max = 1 - a[fl];
}
else {
int mid = (fl + fr) >> 1;
build(ls(x), fl, mid);
build(rs(x), mid + 1, fr);
pushup(x);
}
}
inline void updt(int x, int fl, int fr, int val) {
if (tr[x].l >= fl && tr[x].r <= fr) {
if (val == 0) {
tr[x].sum = 0;
tr[x].lmax = tr[x].rmax = tr[x].smax = 0;
tr[x].l0max = tr[x].r0max = tr[x].s0max = tr[x].r - tr[x].l + 1;
}
else if (val == 1) {
tr[x].sum = tr[x].r - tr[x].l + 1;
tr[x].lmax = tr[x].rmax = tr[x].smax = tr[x].r - tr[x].l + 1;
tr[x].l0max = tr[x].r0max = tr[x].s0max = 0;
}
else if (val == 2) {
tr[x].sum = (tr[x].r - tr[x].l + 1) - tr[x].sum;
swap(tr[x].lmax, tr[x].l0max);
swap(tr[x].rmax, tr[x].r0max);
swap(tr[x].smax, tr[x].s0max);
}
tr[x].lazy = val;
return;
}
pushdown(x);
int mid = (tr[x].l + tr[x].r) >> 1;
if (fl <= mid) updt(ls(x), fl, fr, val);
if (fr > mid) updt(rs(x), fl, fr, val);
pushup(x);
}
inline node qry(int x, int fl, int fr) {
if (tr[x].l >= fl && tr[x].r <= fr) {
return tr[x];
}
pushdown(x);
int mid = (tr[x].l + tr[x].r) >> 1;
// 只在左半边
if (fr <= mid) {
return qry(ls(x), fl, fr);
}
// 只在右半边
if (fl > mid) {
return qry(rs(x), fl, fr);
}
// 跨越中点
node left = qry(ls(x), fl, mid);
node right = qry(rs(x), mid + 1, fr);
node ans;
ans.sum = left.sum + right.sum;
ans.smax = max({ left.smax, right.smax, left.rmax + right.lmax });
// 计算lmax:从查询区间左边界开始的最长连续1
ans.lmax = left.lmax;
if (left.sum == mid - fl + 1) { // 左半部分[fl,mid]全是1
ans.lmax += right.lmax;
}
// 计算rmax:到查询区间右边界结束的最长连续1
ans.rmax = right.rmax;
if (right.sum == fr - mid) { // 右半部分[mid+1,fr]全是1
ans.rmax += left.rmax;
}
return ans;
}
int main(void) {
int n = 0, m = 0;
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
build(1, 0, n - 1);
for (int i = 1; i <= m; i++) {
int l, r, t;
cin >> t >> l >> r;
if (t == 0) {
updt(1, l, r, 0);
}
else if (t == 1) {
updt(1, l, r, 1);
}
else if (t == 2) {
updt(1, l, r, 2);
}
else {
auto k = qry(1, l, r);
if (t == 3) {
cout << k.sum << endl;
}
else if (t == 4) {
cout << k.smax << endl;
}
}
}
return 0;
}
回复
共 0 条回复,欢迎继续交流。
正在加载回复...