[SCOI2010] 序列操作
题目描述
lxhgww 最近收到了一个 \(01\) 序列,序列里面包含了 \(n\) 个数,下标从 \(0\) 开始。这些数要么是 \(0\),要么是 \(1\),现在对于这个序列有五种变换操作和询问操作:
-
0 l r
把 \([l, r]\) 区间内的所有数全变成 \(0\) -
1 l r
把 \([l, r]\) 区间内的所有数全变成 \(1\) -
2 l r
把 \([l,r]\) 区间内的所有数全部取反,也就是说把所有的 \(0\) 变成 \(1\),把所有的 \(1\) 变成 \(0\) -
3 l r
询问 \([l, r]\) 区间内总共有多少个 \(1\) -
4 l r
询问 \([l, r]\) 区间内最多有多少个连续的 \(1\)
对于每一种询问操作,lxhgww 都需要给出回答,聪明的程序员们,你们能帮助他吗?
输入格式
第一行两个正整数 \(n,m\),表示序列长度与操作个数。
第二行包括 \(n\) 个数,表示序列的初始状态。
接下来 \(m\) 行,每行三个整数,表示一次操作。
输出格式
对于每一个询问操作,输出一行一个数,表示其对应的答案。
样例 #1
样例输入 #1
10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9
样例输出 #1
5
2
6
5
提示
【数据范围】
对于 \(30\%\) 的数据,\(1\le n,m \le 1000\);
对于\(100\%\) 的数据,\(1\le n,m \le 10^5\)。
二百行!
就为了维护线段树信息无脑加信息就得了
但是变量多了很容易乱
细节出错很要命
写线段树之前要把每个信息维护的细节想清楚写下来再下手写
边写边想很多细节会忘掉
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+9;
int n,m;
#define ls p<<1
#define rs p<<1|1
int a[N];
struct tree
{
int l,r,sum,ans0,ans,pre1,pre0,sub1,sub0,add0,add1,add;
tree()
{
l = r = sum = ans0 = pre1 = sub1 = add0 = add1 = add = pre0 = sub0 = ans = 0;
}
void col0()
{
add0 = 1;
sum = pre1 = sub1 = add1 = add = ans = 0;
ans0 = pre0 = sub0 = (r-l+1);
}
void col1()
{
add1 = 1;
sum = pre1 = sub1 = ans = (r-l+1);
ans0 = pre0 = sub0 = add0 = add = 0;
}
void col()
{
add ^= 1;
sum = (r-l+1-sum);
swap(add0,add1);
swap(pre1,pre0);
swap(sub1,sub0);
swap(ans,ans0);
}
#define l(x) t[x].l
#define r(x) t[x].r
#define sum(x) t[x].sum
#define ans(x) t[x].ans
#define ans0(x) t[x].ans0
#define pre1(x) t[x].pre1
#define pre0(x) t[x].pre0
#define sub1(x) t[x].sub1
#define sub0(x) t[x].sub0
#define add1(x) t[x].add1
#define add0(x) t[x].add0
#define add(x) t[x].add
}t[N<<1];
tree operator +(const tree &l,const tree &r)
{
tree p;
p.add = p.add0 = p.add1 = 0;
p.l = l.l,
p.r = r.r;
p.sum = l.sum+r.sum;
if(l.pre1 == (l.r-l.l+1))p.pre1 = (l.r-l.l+1) + r.pre1;
else p.pre1 = l.pre1;
if(r.sub1 == (r.r-r.l+1))p.sub1 = l.sub1 + (r.r-r.l+1);
else p.sub1 = r.sub1;
if(l.pre0 == (l.r-l.l+1))p.pre0 = (l.r-l.l+1) + r.pre0;
else p.pre0 = l.pre0;
if(r.sub0 == (r.r-r.l+1))p.sub0 = l.sub0 + (r.r-r.l+1);
else p.sub0 = r.sub0;
p.ans = max(l.ans,r.ans);
p.ans = max(p.ans,l.sub1+r.pre1);
p.ans0 = max(l.ans0,r.ans0);
p.ans0 = max(p.ans0,l.sub0+r.pre0);
return p;
}
void pushup(int p)
{
t[p] = t[ls] + t[rs];
}
void pushdown(int p)
{
if(add(p))
{
t[ls].col();
t[rs].col();
add(p) = 0;
}
if(add0(p))
{
t[ls].col0();
t[rs].col0();
add0(p) = 0;
}
else if(add1(p))
{
t[ls].col1();
t[rs].col1();
add1(p) = 0;
}
}
void build(int p,int l,int r)
{
if(l == r)
{
l(p) = r(p) = l;
if(a[l])t[p].col1();
else t[p].col0();
return;
}
int mid = (l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(p);
}
void modify0(int p,int l,int r)
{
if(l <= l(p) && r >= r(p))
{
t[p].col0();
return;
}
pushdown(p);
int mid = (l(p)+r(p))>>1;
if(l <= mid)modify0(ls,l,r);
if(r > mid)modify0(rs,l,r);
pushup(p);
}
void modify1(int p,int l,int r)
{
if(l <= l(p) && r >= r(p))
{
t[p].col1();
return;
}
pushdown(p);
int mid = (l(p)+r(p))>>1;
if(l <= mid)modify1(ls,l,r);
if(r > mid)modify1(rs,l,r);
pushup(p);
}
void modify(int p,int l,int r)
{
if(l <= l(p) && r >= r(p))
{
t[p].col();
return;
}
pushdown(p);
int mid = (l(p)+r(p))>>1;
if(l <= mid)modify(ls,l,r);
if(r > mid)modify(rs,l,r);
pushup(p);
}
tree query(int p,int l,int r)
{
if(l <= l(p) && r >= r(p))return t[p];
pushdown(p);
int mid = (l(p)+r(p))>>1;
if(r <= mid)return query(ls,l,r);
else if(l > mid)return query(rs,l,r);
else return query(ls,l,r) + query(rs,l,r);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)scanf("%d",&a[i]);
build(1,1,n);
while(m--)
{
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
l++,r++;
if(op == 0)modify0(1,l,r);
else if(op == 1)modify1(1,l,r);
else if(op == 2)modify(1,l,r);
else if(op == 3)printf("%d\n",query(1,l,r).sum);
else printf("%d\n",query(1,l,r).ans);
}
return 0;
}
标签:return,rs,int,线段,mid,毒瘤,序列,query
From: https://www.cnblogs.com/AC7-/p/16828253.html