codeforcesC - Berry Jam(折半枚举+1-1序列前后缀和)
阅读原文时间:2023年07月09日阅读:1

Educational Codeforces Round 78 (Rated for Div. 2) C - Berry Jam

C. Berry Jam

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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

All the 2n2n 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 nn jars to his left and nn 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 11 jar to his left and then 55 jars to his right. There remained exactly 33 full jars of both strawberry and blueberry jam.

Jars are numbered from 11 to 2n2n from left to right, so Karlsson initially stands between jars nn and n+1n+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 tt independent test cases.

Input

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

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

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

It is guaranteed that the sum of nn over all test cases does not exceed 105105.

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.

input

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

  output

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 66 jars so that there remain 00 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 11 jar of both jams.

题目就是要你查找【1~n】和【n+1~2n】两个区间的2和1相同的最小位置差,2是蓝莓,1是草莓,一个人站在n和n+1之间,开始向两边吃,问你怎么在吃的罐数最少情况下,2蓝莓和1草莓两个的总数量上相同。

我们可以把蓝莓2变成-1,1草莓任然为1变成1-1序列,求【1~n】前缀和 和 【n+1~2n】的后缀和

直接n*n暴力枚举:

n=10的5次方必然超时,所以我们不能这么暴力。

折半枚举:

我们可以看到,数组分成两个区间:【1~n】和【n+1~2n】。我们把前一半区间【1~n】的前缀和 和下标位置先保存起来,用map记录结果就不用考虑正负,用标记数组就要记得加上一个偏移量比如100000.

然后for循环一一枚举【n+1~2n】的区间判断是否有【1~n】前缀和 和 【n+1~2n】的后缀和相加为0的位置,取最小的位置差

需要注意的是:某位置后缀和其实可以通过2*n的后缀和-该位置的前缀和直接求出,所以我们不需要先求。

AC代码:

#include
using namespace std;
#define ll long long int
#define M 200005
int inf=0x3f3f3f3f;
int sum[M];int c[M];
int main(void)
{
int t,n,a;
scanf("%d",&t);
while(t--)
{
//初始化
scanf("%d",&n);
for(int i=0;i<=200003;i++) c[i]=inf; sum[0]=0; for(int i=1;i<=n*2;i++){ scanf("%d",&a); if(a>1) a=-1;
sum[i]=sum[i-1]+a;//前缀和
if(i<=n)//记录前n的位置
c[sum[i]+100000]=i;
}
///折半枚举
if(c[0+100000]==inf)
c[0+100000]=0;
int minn=inf;
for(int j=n;j<=2*n;j++){
int h=sum[2*n]-sum[j];//j的后缀和(不包括j)
if(c[-h+100000]!=inf)//找和为0的位置
{
minn=min(minn,j-c[-h+100000]);
}
}
printf("%d\n",minn);
}
return 0;
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章