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)个数( eq)(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)( eq0),设(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
");
			else if((r-l)&1) printf("2
");
			else printf("1
");
		}
	}
}
作者:xxy
本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15234002.html