洛谷 P2574 XOR的艺术(线段树 区间异或 区间求和)
题目描述
AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏。在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下
1、 拥有一个伤害串为长度为n的01串。
2、 给定一个范围[l,r],伤害为伤害串的这个范围内中1的个数
3、 会被随机修改伤害串中的数值,修改的方法是把[l,r]中的所有数xor上1
AKN想知道一些时刻的伤害,请你帮助他求出这个伤害
输入输出格式
输入格式:
第一行两个数n,m,表示长度为n的01串,有m个时刻
第二行一个长度为n的01串,为初始伤害串
第三行开始m行,每行三个数p,l,r
若p为0,则表示当前时刻改变[l,r]的伤害串,改变规则如上
若p为1,则表示当前时刻AKN想知道[l,r]的伤害
输出格式:
对于每次询问伤害,输出一个数值伤害,每次询问输出一行
输入输出样例
输入样例#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
说明
样例解释:
1011101001
1100101001
询问[1,5]输出3
1111010001
询问[1,10]输出6
0000010001
询问[2,6]输出1
数据范围:
10%数据2≤n,m≤10
另有30%数据2≤n,m≤2000
100%数据2≤n,m≤2*10^5
By:worcher
思路:
线段树,只需要把Lazy标记部分改一下。
代码:
1 #include<cstdio> 2 using namespace std; 3 const int N=200005; 4 5 int n,m,Sum[N<<2],Lazy[N<<2]; 6 //char str[N]; 7 8 void read(int &now) 9 { 10 now=0;char c=getchar(); 11 while(c<'0'||c>'9')c=getchar(); 12 while(c>='0'&&c<='9')now=now*10+c-'0',c=getchar(); 13 } 14 15 void PushUp(int rt) 16 { 17 Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1]; 18 } 19 void PushDown(int rt,int m) 20 { 21 if(Lazy[rt]) 22 { 23 Lazy[rt<<1]^=1; 24 Lazy[rt<<1|1]^=1; 25 Sum[rt<<1]=(m-(m>>1))-Sum[rt<<1];//异或(取反),将原先状态全部翻转 26 Sum[rt<<1|1]=(m>>1)-Sum[rt<<1|1];//该区间一共(r-l+1)>>1 个元素,减去自己即为异或后状态 27 Lazy[rt]=0; 28 } 29 } 30 void Build(int l,int r,int rt) 31 { 32 Lazy[rt]=0; 33 if(l==r) 34 { 35 int a; 36 scanf("%1d",&a); 37 Sum[rt]= a?1:0; 38 //Sum[rt]= str[l]=='1'?1:0; 39 return; 40 } 41 int m=(l+r)>>1; 42 Build(l,m,rt<<1); 43 Build(m+1,r,rt<<1|1); 44 PushUp(rt); 45 } 46 void ModifyXor(int l,int r,int rt,int L,int R) 47 { 48 if(L<=l && r<=R) 49 { 50 Lazy[rt]^=1; 51 Sum[rt]=r-l+1-Sum[rt]; 52 return; 53 } 54 PushDown(rt,r-l+1); 55 int m=(l+r)>>1; 56 if(L<=m) ModifyXor(l,m,rt<<1,L,R); 57 if(m<R) ModifyXor(m+1,r,rt<<1|1,L,R); 58 PushUp(rt); 59 } 60 int QuerySum(int l,int r,int rt,int L,int R) 61 { 62 if(L<=l && r<=R) return Sum[rt]; 63 PushDown(rt,r-l+1); 64 int m=(l+r)>>1,res=0; 65 if(L<=m) res+=QuerySum(l,m,rt<<1,L,R); 66 if(m<R) res+=QuerySum(m+1,r,rt<<1|1,L,R); 67 return res; 68 } 69 70 int main() 71 { 72 read(n);read(m);//scanf("%s",str+1); 73 Build(1,n,1); 74 for(int i=1;i<=m;i++) 75 { 76 int p,l,r; 77 read(p);read(l);read(r); 78 if(p) 79 printf("%d\n",QuerySum(1,n,1,l,r)); 80 else 81 ModifyXor(1,n,1,l,r); 82 } 83 return 0; 84 }
------------------------------------------------------------------------------------------------------------------------
很久以前的奇怪但现在依旧成立的签名
attack is our red sun $$\color{red}{\boxed{\color{red}{attack\ is\ our\ red\ sun}}}$$ ------------------------------------------------------------------------------------------------------------------------
很久以前的奇怪但现在依旧成立的签名
attack is our red sun $$\color{red}{\boxed{\color{red}{attack\ is\ our\ red\ sun}}}$$ ------------------------------------------------------------------------------------------------------------------------