C. Berry Jam-----思维+转换+前缀和+后缀和(难)

Karlsson has recently discovered a huge stock of berry jam jars in the basement of the house. More specifically, there were 2n jars of strawberry and blueberry jam.

All the 2n jars are arranged in a row. The stairs to the basement are exactly in the middle of that row. So when Karlsson enters the basement, he sees exactly n jars to his left and n jars to his right.

For example, the basement might look like this:

Being the starightforward man he is, he immediately starts eating the jam. In one minute he chooses to empty either the first non-empty jar to his left or the first non-empty jar to his right.

Finally, Karlsson decided that at the end the amount of full strawberry and blueberry jam jars should become the same.

For example, this might be the result:

He has eaten 1 jar to his left and then 5 jars to his right. There remained exactly 3 full jars of both strawberry and blueberry jam.
Jars are numbered from 1 to 2n from left to right, so Karlsson initially stands between jars n and n+1.

What is the minimum number of jars Karlsson is required to empty so that an equal number of full strawberry and blueberry jam jars is left?

Your program should answer t independent test cases.

Input
The first line contains one integer t (1≤t≤1000) — the number of test cases.

The first line of each test case contains a single integer n (1≤n≤105).

The second line of each test case contains 2n integers a1,a2,…,a2n (1≤ai≤2) — ai=1 means that the i-th jar from the left is a strawberry jam jar and ai=2 means that it is a blueberry jam jar.

It is guaranteed that the sum of n over all test cases does not exceed 105.

Output
For each test case print the answer to it — the minimum number of jars Karlsson is required to empty so that an equal number of full strawberry and blueberry jam jars is left.

Example
inputCopy

4
6
1 1 1 2 2 1 2 1 2 1 1 2
2
1 2 1 2
3
1 1 1 1 1 1
2
2 1 1 1
outputCopy
6
0
6
2
Note
The picture from the statement describes the first test case.

In the second test case the number of strawberry and blueberry jam jars is already equal.

In the third test case Karlsson is required to eat all 6 jars so that there remain 0 jars of both jams.

In the fourth test case Karlsson can empty either the second and the third jars or the third and the fourth one. The both scenarios will leave 1 jar of both jams.

题意:一共有2*n个罐子,为红蓝。你现在处于中间位置,问你最小去除多少个罐子使得红蓝罐子相同

解析:因为只有两种罐子,所以我们把序列变为1,-1.然后维护一个前缀和数组。第i个可以代表这个区间内有多少个多余的(即大于另一个罐子数)因为是从中间开始的,对于左边我们用一个map存储每一个数最后出现的位置。然后我们再看右边用当前位置i的前缀和-2 * n的前缀和(就可以得到(i+1~~2*n)的后缀和),得到的这个值为x我们看看在前面是否出现过,若出现了答案为min(i-map[x]).但是我们需要对map[0]=0初始化。

或者换一个理解方式:把输入的2变成-1,我们只需要找到一个n之前的前缀和(包括n),和n之后的后缀和,使得他们的和为0

或者:左边的前缀和如果>0,肯定是多了好几个1,右边的后缀和如果>0,肯定是多了好几个-1 这样子使他们的和为0即可



#include<bits/stdc++.h>
using namespace std;
const int N=1e6+1000;
int sum[N];
map<int,int> v;
int a[N];
int t,n;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		memset(sum,0,sizeof sum);
		v.clear();
		v[0]=0;//初始 
		for(int i=1;i<=2*n;i++) 
		{
			scanf("%d",&a[i]);
			if(a[i]==2) a[i]=-1;
			sum[i]=sum[i-1]+a[i];
			if(i<=n) v[sum[i]]=i;
		}
		int ans=2*n;
		for(int i=n;i<=2*n;i++)
		{
			int x=sum[i]-sum[2*n]; //用前缀和求出后缀和(i-2*n)->实际对应后缀和((i+1~2*n)的值) 
			if(v.find(x)!=v.end()) ans=min(ans,i-v[x]);
		}
		cout<<ans<<endl;
	}
 } 
发布了309 篇原创文章 · 获赞 6 · 访问量 5253

猜你喜欢

转载自blog.csdn.net/qq_43690454/article/details/104084074
今日推荐