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");
}
}
}