Berry Jam

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.

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≤10^5)\).

The second line of each test case contains 2n integers \(a_1,a_2,…,a_{2n} (1≤a_i≤2)\)\(a_i=1\) means that the i-th jar from the left is a strawberry jam jar and \(a_i=2\) means that it is a blueberry jam jar.

It is guaranteed that the sum of n over all test cases does not exceed \(10^5\)

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

题意: 给定2n长度数组, 从中间开始删除, 求删除长度的最小值使得两种果酱数目一样.
把2换成-1,即求最小长度使得前缀和为0.
设s[i]为前缀和, 固定区间左端点i, 即求合法位置的一个最左边的右端点j 使得 s[j]-s[i-1]==s[2n]
显然,j合法的位置是\([n,2n]\), 用pos[v]数组记录n右边最靠近n的v的位置.
ans=0特判
前缀和范围是\([-2n,2n]\),整体加上2n
不可能的v值直接continue

#include<bits/stdc++.h>
using namespace std;
char buf[1<<20],*_=buf,*__=buf;
#define gc() (_==__&&(__=(_=buf)+fread(buf,1,1<<20,stdin),_==__)?EOF:*_++)
#define TT template<class T>inline
TT bool read(T &x){
    x=0;char c=gc();bool f=0;
    while(c<48||c>57){if(c==EOF)return 0;f^=(c=='-'),c=gc();}
    while(47<c&&c<58)x=(x<<3)+(x<<1)+(c^48),c=gc();
    if(f)x=-x;return 1;
}
const int MAXN=1e5+8;
int s[MAXN],pos[MAXN<<2];
int main() {
    int t,n,nn;read(t);
    while(t--){
        read(n);nn=n<<1;
        memset(pos,-1,sizeof(pos));
        for(int i=1,x;i<=nn;++i){
            read(x);
            s[i]=s[i-1]-2*x+3;
        }
        for(int i=n<<1;i>=n;--i)pos[s[i]+nn]=i;
        int d=s[nn],ans=nn;
        if(d!=0)for(int i=n+1;i;--i){
            if(d+s[i-1]+nn<0||d+s[i-1]>nn)continue;//不可能的值
            int j=pos[d+s[i-1]+nn];
            if(n-i+1>ans)break;//不可能有更小的ans了
            if(i<=j)ans=min(ans,j-i+1);
        }
        else ans=0;//特判
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2020-12-19 23:01  肆之月  阅读(87)  评论(0编辑  收藏  举报