Description
Solution
首先把数列转化成距离目标矩阵所需要的步数,设为
C
,则
那么这就是一个粉刷栅栏的问题。
首先对 Ci 差分,即 Ci=Ci−Ci+1 。那么答案为 ∑ni=1max(Ci,0) 。
问题是我们可以给任意一面栅栏的高度增加4。那么如果对一个位置
i
高度增加4,那么
对于一个区间 (l,r] 高度都增加4,那么影响的只有头尾,也就是 Cl−4 , Cr+4 。
Cl=0 是不用理的。
如果 Cl=1 ,那么答案是不会减少的,因为即使 Cr=−3 ,所需要的步数还是1。
如果 Cl=2 ,只有在 Cr=−3 时,答案才会减少1。
如果 Cl=3 ,那么当 Cr=2 时,答案会减少1, Cr=3 时,答案会减少2。
于是我们正着枚举数列,统计2、3的个数。然后-2与3匹配,-3与3,2匹配。
这里注意-3和3匹配更优,那么如果-2和3匹配了,那么后面的-3是可以使当前的匹配再减少1答案(也就是尽量让-3和3匹配)。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 100001
using namespace std;
int a[N],b[N],c[N];
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
scanf("%d",&n);
fo(i,1,n) scanf("%d",&a[i]);
fo(i,1,n)
{
int x;
scanf("%d",&x);
c[i]=x-a[i];
if(c[i]<0) c[i]+=4;
}
int ans=0;
fo(i,1,n) c[i]-=c[i+1],ans+=(c[i]>0?c[i]:0);
int t2=0,t3=0;
fo(i,1,n)
{
if(c[i]==2) t2++;
if(c[i]==3) t3++;
if(c[i]==-2)
{
if(t3) t2++,t3--,ans--;
}
else if(c[i]==-3)
{
if(t3) t3--,ans-=2;
else if(t2) t2--,ans--;
}
}
printf("%d\n",ans);
}
}