Codeforces Round #540 (Div. 3)--B. Tanya and Candies(前缀和的运用与变化)

Tanya and Candies

题目链接http://codeforces.com/problemset/problem/1118/B
time limit per test:1 second
memory limit per test:256 megabytes

Codeforces Round #540 (Div. 3)--B. Tanya and Candies(前缀和的运用与变化)
Codeforces Round #540 (Div. 3)--B. Tanya and Candies(前缀和的运用与变化)

Examples

Input
7
5 5 4 5 5 5 6

Output
2

Input
8
4 8 8 7 8 4 4 5

Output
2

Input
9
2 3 4 2 2 3 2 2 4

Output
3

Note

In the first example indices of good candies are [1,2]
.

In the second example indices of good candies are [2,3]
.

In the third example indices of good candies are [4,5,9]
.


题目大意:给你n个数从中删去一个位置使得奇数位的和=偶数位的和,问你有多少种删法。
emmm。。。最朴素的算法就是一个个删掉然后一个个加起来查询。不过这样肯定会超时。毕竟是n2的算法。但它既然要求的是和,那么我们很容易想到可以用前缀和来优化使它达到O(n):

if (i&1) odd[i]=odd[i-1]+a[i],even[i]=even[i-1];
else even[i]=even[i-1]+a[i],odd[i]=odd[i-1]; 

即构造两个前缀和,一个存奇数一个存偶数。
不过前缀和是静态的,这里删去了一个数之后整个数列就有所变化。不过我们细心一些就会发现,删去第i个数之后,i前面的i-1个数的奇偶性是不变的,则它们的和依旧是sum[i-1]。i之后的数奇偶性就会颠倒,则它们的和就相反了,即偶数=原本奇数的前缀和,奇数=原本偶数的前缀和。

#include <cstdio>
int a[200050],odd[200050],even[200050];
int main()
{
	int n,num=1;
	scanf ("%d",&n);
	for (int i=1; i<=n; i++){
		scanf ("%d",&a[i]);
		if (i&1) odd[i]=odd[i-1]+a[i],even[i]=even[i-1];
		else even[i]=even[i-1]+a[i],odd[i]=odd[i-1]; 
	}
	num--;
	int odd2=0,even2=0,ans=0;
	for (int i=1; i<=n; i++){//枚举删去第i天
		odd2=0,even2=0;
		if (i&1){
			odd2=odd[i]-a[i];
			even2=even[i];   //i之前奇偶不变
			odd2+=even[n]-even[i];//i之后奇偶颠倒
			even2+=odd[n]-odd[i];
		}
		else {
			odd2=odd[i];
			even2=even[i]-a[i];
			odd2+=even[n]-even[i];
			even2+=odd[n]-odd[i];
		}
		if (odd2==even2) ans++;
	}
	printf ("%d\n",ans);
	return 0;
}