P2574
XOR的艺术
题目描述
AKN 觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏。在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下
-
拥有一个伤害串,是一个长度为 \(n\) 的只含字符
0和字符1的字符串。规定这个字符串的首字符是第一个字符,即下标从 \(1\) 开始。 -
给定一个范围 \([l,~r]\),伤害为伤害串的这个范围内中字符
1的个数 -
会修改伤害串中的数值,修改的方法是把 \([l,~r]\) 中所有原来的字符
0变成1,将1变成0。
AKN 想知道一些时刻的伤害,请你帮助他求出这个伤害。
输入格式
输入的第一行有两个用空格隔开的整数,分别表示伤害串的长度 \(n\),和操作的个数 \(m\)。
输入第二行是一个长度为 \(n\) 的字符串 \(S\),代表伤害串。
第 \(3\) 到第 \((m + 2)\) 行,每行有三个用空格隔开的整数 \(op, l, r\)。代表第 \(i\) 次操作的方式和区间,规则是:
- 若 \(op = 0\),则表示将伤害串的 \([l,~r]\) 区间内的
0变成1,1变成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;
}

浙公网安备 33010602011771号