毒瘤线段树

就为了维护线段树信息无脑加信息就得了
怎么维护起来方便就加啥
但是变量多了很容易乱
细节出错很要命
所以很考察你的细心(耐心)能力并让你砸烂键盘
写线段树之前要把每个信息维护的细节想清楚写下来再下手写
边写边想很多细节会忘掉
取反操作要注意顺序其他较简单

[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\)


std:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+9;//最后一个hack数据2e5 题面没写 
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;//12个-_- 
	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;//注意直接用区间长度不要用sum 
	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;//注意直接用区间长度不要用sum 
	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)
{
	//注意靠考虑取反和全覆盖之间的顺序
	//add0()在最后加入时add1()与add()都不存在 即使存在也会被清空
	//add1()在最后加入时add0()与add()都不存在 即使存在也会被清空
	//add() 在最后加入时(add0()与add1()都不存在)或(add0()与add1()其中一个存在) 
	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 modify(int p,int l,int r,int op)
{
	if(l <= l(p) && r >= r(p))
	{
		if(op == 0)t[p].col0();
		else if(op == 1)t[p].col1();
		else if(op == 2)t[p].col();
		return;
	}
	
	pushdown(p);
	
	int mid = (l(p)+r(p))>>1;
	if(l <= mid)modify(ls,l,r,op);
	if(r > mid)modify(rs,l,r,op);
	
	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)modify(1,l,r,0);
		else if(op == 1)modify(1,l,r,1);
		else if(op == 2)modify(1,l,r,2);
		else if(op == 3)printf("%d\n",query(1,l,r).sum);
		else printf("%d\n",query(1,l,r).ans);
	}
	return 0;
}
posted @ 2022-10-26 14:25  AC7  阅读(55)  评论(0)    收藏  举报