2020.01.03日常总结

洛谷P2574

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

( 1 ) (1) 拥有一个伤害串为长度为 n n 01 01 串。

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

( 3 ) (3) 会被随机修改伤害串中的数值,修改的方法是把[l,r]中的所有数 x o r xor 1 1 (即 0 0 1 1 1 1 0 0 )。

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

【思路】: 线段树的题目。

L e n [ l , r ] Len[l,r] 表示区间 ( l , r ) (l,r) 的长度, S u m [ l , r ] Sum[l,r] 表示区间 ( l , r ) (l,r) 1 1 的个数。

首先考虑修改操作,我们发现修改操作会让每个数 0 0 1 1 1 1 0 0 ,所以总和(即 1 1 的个数) S u m [ l , r ] = L e n [ l , r ] S u m [ l , r ] Sum[l,r]=Len[l,r]-Sum[l,r]

举个例子,比如原来的数串为0001101,其总和为 3 3 。修改后变为1110010,总和为 7 3 = 4 7-3=4

然后,我们就可以很容易联想到线段树了。

【代码】:

const int N=2e5+100;
int Len[N<<2],sum[N<<2];
bool add[N<<2];int n,m;
inline void pushup(int o){
	sum[o]=sum[o<<1]+sum[o<<1|1];
}//pushup(o):标记上传操作
inline void pushdown(int o){
	sum[o<<1]=Len[o<<1]-sum[o<<1];
	sum[o<<1|1]=Len[o<<1|1]-sum[o<<1|1];
	add[o<<1]^=1;add[o<<1|1]^=1;add[o]=0;
}//pushdown(o):标记下传操作
int a[N],opt,x,y;string s;
void build(int o,int l,int r){
	Len[o]=r-l+1;
	if (l==r){
		sum[o]=a[l];
		add[o]=0;
		return;
	}
	register int mid=(l+r)>>1;
	build(o<<1,l,mid);
	build(o<<1|1,mid+1,r);
	pushup(o);return;
}//建树操作
void updata(int o,int l,int r,int p,int q){
	if (l>q||r<p) return;
	if (p<=l&&r<=q){
		sum[o]=Len[o]-sum[o];
		add[o]^=1;return;
	}
	if (add[o]) pushdown(o);
	register int mid=(l+r)>>1;
	updata(o<<1,l,mid,p,q);
	updata(o<<1|1,mid+1,r,p,q);
	pushup(o);return;
}//修改操作
int query(int o,int l,int r,int p,int q){
	if (l>q||r<p) return 0;
	if (p<=l&&r<=q) return sum[o];
	if (add[o]) pushdown(o);
	register int mid=(l+r)>>1;
	register int answer=0;
	answer+=query(o<<1,l,mid,p,q);
	answer+=query(o<<1|1,mid+1,r,p,q);
	return answer;
}//求和(即求答案)操作
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
	char c=0;int x=0;bool f=0;
	while (!g(c)) f=c=='-',c=gc;
	while (g(c)) x=x*10+c-48,c=gc;
	return f?-x:x;
}//快读
int main(){
	n=read();m=read();cin>>s;
	for(int i=0;i<n;i++)
		a[i+1]=s[i]-'0';
	build(1,1,n);
	for(int i=1;i<=m;i++){
		opt=read();x=read();y=read();
		if (opt) printf("%d\n",query(1,1,n,x,y));
		else updata(1,1,n,x,y);
	}
	return 0;
}
发布了82 篇原创文章 · 获赞 4 · 访问量 1768

猜你喜欢

转载自blog.csdn.net/ZHUYINGYE_123456/article/details/103827104
今日推荐