C. Berry Jam(差值前缀,思维)

永久的帅气的无敌的传送门大门校门神门命运石之门

\(考虑枚举左半区间的点l\)

\(试图在右半区间找一个最小的点r\)

\(使得吃掉[l+1,r-1]的奶酪后两种奶酪数量相等\)

\(\color{Red}{于是我们可以预处理右半区间中两种奶酪的差值位置}\)

\(比如r[2]=6,表示在区间[6,2*n]中1奶酪比2奶酪多2个\)

\(r[-1]=9,表示在区间[9,2*n]中1奶酪比2奶酪少1个\)

\(因为存在负数,那么我们把下标都加100000:r[-1+100000]=9\)

\(那么我们开始枚举左半区间的点,比如枚举到2时\)

\(1奶酪比2奶酪多1,那我们就去看看r[-1+100000]的位置\)

\(因为这样可以刚好抵消,两种奶酪相等\)

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+9;
int r[maxn],a[maxn],t,n;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=100000-n;i<=100000+n;i++)	r[i]=0;
		for(int i=1;i<=2*n;i++)	scanf("%d",&a[i]);
		int q=0,w=0,ans=2*n;
		for(int i=2*n;i>=n+1;i--)
		{
			a[i]==1?q++:w++;
			r[q-w+100000]=i;//i右边 
		}
		q=w=0;
		if(!r[100000])	r[100000]=2*n+1;//右边一个都不选,差值为0 
		if(r[100000])	ans=min(ans,r[100000]-1);//左边一个都不选 
		for(int i=1;i<=n;i++)
		{
			a[i]==1?q++:w++;
			if(r[w-q+100000])	ans=min(ans,r[w-q+100000]-i-1);
		}
		cout<<ans<<endl;
	}
}
posted @ 2020-05-16 12:30  倾叶子佮  阅读(159)  评论(0编辑  收藏  举报