P2574

XOR的艺术

题目描述

AKN 觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏。在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下

  1. 拥有一个伤害串,是一个长度为 \(n\) 的只含字符 0 和字符 1 的字符串。规定这个字符串的首字符是第一个字符,即下标从 \(1\) 开始。

  2. 给定一个范围 \([l,~r]\),伤害为伤害串的这个范围内中字符 1 的个数

  3. 会修改伤害串中的数值,修改的方法是把 \([l,~r]\) 中所有原来的字符 0 变成 1,将 1 变成 0

AKN 想知道一些时刻的伤害,请你帮助他求出这个伤害。

输入格式

输入的第一行有两个用空格隔开的整数,分别表示伤害串的长度 \(n\),和操作的个数 \(m\)

输入第二行是一个长度为 \(n\) 的字符串 \(S\),代表伤害串。

\(3\) 到第 \((m + 2)\) 行,每行有三个用空格隔开的整数 \(op, l, r\)。代表第 \(i\) 次操作的方式和区间,规则是:

  • \(op = 0\),则表示将伤害串的 \([l,~r]\) 区间内的 0 变成 11 变成 0
  • \(op = 1\),则表示询问伤害串的 \([l,~r]\) 区间内有多少个字符 1

输出格式

对于每次询问,输出一行一个整数,代表区间内 1 的个数。

样例 #1

样例输入 #1

10 6
1011101001
0 2 4
1 1 5
0 3 7
1 1 10
0 1 4
1 2 6

样例输出 #1

3
6
1

提示

样例输入输出 \(1\) 解释

原伤害串为 1011101001

对于第一次操作,改变 \([2,~4]\) 的字符,伤害串变为 1100101001

对于第二次操作,查询 \([1,~5]\)1 的个数,共有 \(3\) 个。

对于第三次操作,改变 \([3,~7]\) 的字符,伤害串变为 1111010001

对于第四次操作,查询 \([1,~10]\)1 的个数,共有 \(6\) 个。

对于第五次操作,改变 \([1,~4]\) 的字符,伤害串变为 0000010001

对于第六次操作,查询 \([2,~6]\)1 的个数,共有 \(1\) 个。

数据范围与约定

对于 \(10\%\) 的数据,保证 \(n, m \leq 10\)

另有 \(30\%\) 的数据,保证 \(n, m \leq 2 \times 10^3\)

对于 \(100\%\) 的数据,保证 \(2 \leq n, m \leq 2 \times 10^5\)\(0 \leq op \leq 1\)\(1 \leq l \leq r \leq n\)\(S\) 中只含字符 0 和字符 1

其实上一道题是乱搞做法
正解:每次操作相当于对add^=1
区间sum变为len-sum
每次pushdown只要add不为0(反转次数不为偶)那么就修改一次
modify是对add^=1 sum=len-sum即可
注意一定是tr[p].add!=0才pushdown!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,a[200005],m,s[200005]; 
struct tree{
	int l,r,sum,add;
}tr[200005*4];
void pushup(int p)
{
	tr[p].sum=tr[p<<1].sum+tr[p<<1|1].sum;
}
void build(int p,int l,int r)
{
	tr[p].l=l,tr[p].r=r;
	if(l==r)
	{
		tr[p].sum=a[l];
		return ;	
	} 
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	pushup(p);
}
void pushdown(int p)
{
	if(tr[p].add==0)return ;
	tr[p<<1].add^=1;
	tr[p<<1].sum=tr[p<<1].r-tr[p<<1].l+1-tr[p<<1].sum;
	tr[p<<1|1].add^=1;
	tr[p<<1|1].sum=tr[p<<1|1].r-tr[p<<1|1].l+1-tr[p<<1|1].sum;
	tr[p].add=0;
}
void modify(int p,int l,int r,int k)
{
	if(l<=tr[p].l&&r>=tr[p].r)
	{
		tr[p].add^=1;
		tr[p].sum=tr[p].r-tr[p].l+1-tr[p].sum;
		return ;
	}
	pushdown(p);
	int mid=(tr[p].l+tr[p].r)>>1;
	if(l<=mid)modify(p<<1,l,r,k);
	if(r>mid)modify(p<<1|1,l,r,k);
	pushup(p);
}
int query(int p,int l,int r)
{
	if(l<=tr[p].l&&r>=tr[p].r)
	{
		return tr[p].sum;
	}
	pushdown(p);
	int tot=0;
	int mid=(tr[p].l+tr[p].r)>>1;
	if(l<=mid)tot+=query(p<<1,l,r);
	if(r>mid)tot+=query(p<<1|1,l,r);
	return tot;
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	string s;cin>>s;
	for(int i=0;i<n;i++)a[i+1]=s[i]-'0'; 
//	for(int i=1;i<=n;i++)cout<<a[i]<<" ";cout<<"\n";
	build(1,1,n);
	while(m--)
	{
		int op,x,y;
		cin>>op;
		if(op==0)
		{
			cin>>x>>y;
			
			modify(1,x,y,1);
		}
		else
		{
			cin>>x>>y;
			cout<<query(1,x,y)<<"\n";
		}
	}
	return 0;
}
posted @ 2023-01-19 14:36  PKU_IMCOMING  阅读(13)  评论(0)    收藏  举报