Description
Solution
把题目抽象一下,就变成了求序列中,每个点可以上升4,要使下降的总和(∑max(0,a[i−1]−a[i]))最小,
首先,每个点可以上升多次!!!
当一个区间整体上升的时候,影响的就只有开头和结尾,如果要使答案减小,就要符合:
ai−1−ai>aj+4−aj+1
于是我们可以贪心的做,用di表示不等式后面的值等于i的位置有多少个,
每次直接找到一个符合不等式的,使答案上升最小的i,加到答案上去,再di减一;
复杂度:O(n)
Code
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=100500;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n,m,ans;
int a[N],F[10];
int main()
{
int q,_;
read(_);
while(_--)
{
read(n);
fo(i,1,n)read(a[i]);
fo(i,1,n)a[i]=(read(q)-a[i]+4)%4;
F[0]=F[1]=F[2]=F[3]=0;
a[n+1]=0;ans=a[n];
fod(i,n,2)
{
F[a[i]+4-a[i+1]]++;
fo(j,1,a[i-1]-a[i]-1)if(F[j])a[i]+=4,ans+=j,F[j]--;
ans+=max(0,a[i-1]-a[i]);
}
printf("%d\n",ans);
}
return 0;
}