CF1562 D1. Two Hundred Twenty One (easy version)

https://codeforces.com/problemset/problem/1562/D1

题意:
给出一个由1和-1构成的序列,有若干次询问,每次询问一个区间,问最少删除几个数,满足区间内剩下的序列的奇数项减去偶数项=0

结论:
1、若区间原本的奇数项-偶数项的和=0,答案是0
否则,
2、若区间长度为奇数,答案是1
3、若区间长度是偶数,答案是2

2的证明:
\(b_i\)表示一个长度为奇数的区间去掉第i项之后的奇数项减去偶数项
因为\(b_i\)有偶数个数,所以\(b_i\)一定是偶数
若第\(i\)个数=第\(i+1\)个数,那么\(b_i=b_{i+1}\)。这个好理解,因为相邻的这2个数是一个样的,去掉谁都一样。
若第\(i\)个数\(\neq\)\(i+1\)个数,那么\(|b_i-b_{i+1}|=2\)。这是因为去掉这2个数中的某个数,对于\(i\)前面和\(i+1\)后面的数的影响都是一样的。又因为他们两个不一样,所以差值是2。
接下来我们的目标是证明必然存在一个\(i\)满足\(b_i=0\)

设区间长度为\(n\)
\(b_1\)或者\(b_n=0\),那么就删除第\(1\)或者第\(n\)个数即可
\(b_1\)\(b_n\)\(\neq0\),设\(x\)表示第2个数-第3个数+第4个数-第5个数……,则\(x\)必然是奇数
\(b_1=-x±1\)\(b_n=x±1\),可以得出\(b_1\)\(b_n\)不会同时大于0或者同时小于0
\(b_1\)\(b_n\)必然一正一负
而又因为\(|b_i-b_{i+1}|=2\)\(b_i\)一定是偶数,所以必然存在一个\(i\)满足\(b_i=0\)

3的证明:
\(b_i\)表示一个长度为偶数的区间去掉第i项之后的奇数项减去偶数项
因为\(b_i\)有奇数个数,所以\(b_i\)一定是奇数
所以删除1个肯定不行
删除1个之后区间长度变为奇数,由结论2可得,再删除1个必然有解

#include<bits/stdc++.h>

#define N 300002

char s[N]; 
int a[N];

int sum(int l,int r)
{ 
	if(l&1) return a[r]-a[l-1];
	return a[l-1]-a[r];
}

int main()
{
	int T,n,m,l,r;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d%s",&n,&m,s+1);
		for(int i=1;i<=n;++i) a[i]=s[i]=='+' ? 1 : -1;
		for(int i=1;i<=n;++i) 
			if(i&1) a[i]=a[i-1]+a[i];
			else a[i]=a[i-1]-a[i];
		while(m--)
		{
			scanf("%d%d",&l,&r);
			if(!sum(l,r)) printf("0\n");
			else if((r-l)&1) printf("2\n");
			else printf("1\n");
		}
	}
}
posted @ 2021-09-06 15:39  TRTTG  阅读(87)  评论(0编辑  收藏  举报