P2574 XOR的藝術 | 洛谷

P2574 XOR的藝術

AKN 覺得第一題太水了,不屑於寫第一題,所以他又玩起了新的遊戲。在遊戲中,他發現,這個遊戲的傷害計算有一個規律,規律如下

擁有一個傷害串,是一個長度爲 nn 的只含字符 0 和字符 1 的字符串。規定這個字符串的首字符是第一個字符,即下標從 11 開始。

給定一個範圍 [l,~r][l, r],傷害爲傷害串的這個範圍內中字符 1 的個數

會修改傷害串中的數值,修改的方法是把 [l,~r][l, r] 中所有原來的字符 0 變成 1,將 1 變成 0。

AKN 想知道一些時刻的傷害,請你幫助他求出這個傷害。

輸入格式
輸入的第一行有兩個用空格隔開的整數,分別表示傷害串的長度 nn,和操作的個數 mm。

輸入第二行是一個長度爲 nn 的字符串 SS,代表傷害串。

第 33 到第 (m + 2)(m+2) 行,每行有三個用空格隔開的整數 op, l, rop,l,r。代表第 ii 次操作的方式和區間,規則是:

若 op = 0op=0,則表示將傷害串的 [l,~r][l, r] 區間內的 0 變成 1,1 變成 0。
若 op = 1op=1,則表示詢問傷害串的 [l,~r][l, r] 區間內有多少個字符 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
說明/提示
樣例輸入輸出 11 解釋
原傷害串爲 1011101001。

對於第一次操作,改變 [2,~4][2, 4] 的字符,傷害串變爲 1100101001。

對於第二次操作,查詢 [1,~5][1, 5] 內 1 的個數,共有 33 個。

對於第三次操作,改變 [3,~7][3, 7] 的字符,傷害串變爲 1111010001。

對於第四次操作,查詢 [1,~10][1, 10] 內 1 的個數,共有 66 個。

對於第五次操作,改變 [1,~4][1, 4] 的字符,傷害串變爲 0000010001。

對於第六次操作,查詢 [2,~6][2, 6] 內 1 的個數,共有 11 個。

數據範圍與約定
對於 10%10% 的數據,保證 n, m \leq 10n,m≤10。

另有 30%30% 的數據,保證 n, m \leq 2 \times 10^3n,m≤2×10
3

對於 100%100% 的數據,保證 2 \leq n, m \leq 2 \times 10^52≤n,m≤2×10
5
,0 \leq op \leq 10≤op≤1,1 \leq l \leq r \leq n1≤l≤r≤n,SS 中只含字符 0 和字符 1。
思路
線段樹模板修改一下,區間修改用異或1

#include<iostream>
#include<cstdio>
#include<cstdio>
using namespace std;
typedef long long ll;
struct node{
	int l,r;
	ll data,lz;
}tree[4000010]; 
void build(int l,int r,int now)
{
	tree[now].l=l;tree[now].r=r;tree[now].lz=0;
	if(l==r)
	{
		scanf("%1d",&tree[now].data);
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,now*2);
	build(mid+1,r,now*2+1);
	tree[now].data=tree[now*2].data+tree[now*2+1].data;
}
void pushdown(int x,int l)
{
	if(tree[x].lz)
	{
		tree[x*2].lz^=1;
		tree[x*2+1].lz^=1;
		tree[x*2].data=(l-l/2)-tree[x*2].data;
		tree[x*2+1].data=l/2-tree[x*2+1].data;
		tree[x].lz=0;
	}
}
void update(int l,int r,int now)
{
	
	if(tree[now].l>=l&&tree[now].r<=r)
	{
		tree[now].data=tree[now].r-tree[now].l+1-tree[now].data;
		tree[now].lz^=1;
		return; 
	}pushdown(now,tree[now].r-tree[now].l+1);
	if(tree[now*2].r>=l)update(l,r,now*2);
	if(tree[now*2+1].l<=r)update(l,r,now*2+1);
	tree[now].data=tree[now*2].data+tree[now*2+1].data;
}
ll get_sum(int l,int r,int now)
{
	if(tree[now].l>=l&&tree[now].r<=r)
	{
		return tree[now].data;
	}
	pushdown(now,tree[now].r-tree[now].l+1);
	ll ans=0;
	if(tree[now*2].r>=l)ans=ans+get_sum(l,r,now*2);
	if(tree[now*2+1].l<=r)ans=ans+get_sum(l,r,now*2+1);
	return ans;
}
int main()
{
	int n,m,x,y,k,t;
	scanf("%d%d",&n,&m);
	build(1,n,1);
	while(m--)
	{
		scanf("%d%d%d",&t,&x,&y);
		if(t==0)
		{
			update(x,y,1);
		} 
		else 
		{
			printf("%lld\n",get_sum(x,y,1));
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章