题目
给定序列A,B,每一次操作可以让A的i~j这个区间内+1%4,求多少次操作才能让A达到B
先求出对于第i个位置从Ai−>Bi要做多少次,记作Di
如果不考虑模的话,这题就是一个经典的粉刷问题,
Ans=∑Di−Di−1|(Di>Di−1)
然后我们再考虑模,如果操作次数+4对正确性没有影响,那么我们什么时候才需要让某个地方再做4次以达到答案减小的目的呢,不难发现就是这种情况。
如果这样的话我们的代价其实就是 左右两边的和 减去 中间的 (假设中间的是相同高度)
我们可以让中间全部加4,以此达到可以一次做完 那么这样答案就是左边的高度加上中间加四后高出来的高度
我们可以算出,在左边我们需要增加了多少次,在右边减去了多少,然后统计一下需要增加X次的个数(统计相邻的),这样我们每次找到一个最不亏的(亏的话干脆不加),就把答案加上增加的次数再减去少掉的次数就可以了。
CODE
#include <cstdio>
#include <iostream>
#include <cstring>
#define N 100010
using namespace std;
int a[N],b[N],n,t,ans,d[100];
int main() {
cin>>t;
for (int iii=0; iii<t; iii++) {
memset(d,0,sizeof d);
cin>>n;
for (int i=1; i<=n; i++) {
scanf("%d",&a[i]);
}
for (int i=1; i<=n; i++) {
scanf("%d",&b[i]);
a[i]=(b[i]-a[i]+4)%4;
}
ans=a[1];
for (int i=1; i<n; i++) {
if (a[i]<a[i+1]) {
ans+=a[i+1]-a[i];
for (int j=1; j<a[i+1]-a[i]; j++) {
if (d[j]) {
ans-=(a[i+1]-a[i]-j);
d[j]--;
d[a[i+1]-a[i]]++;
break;
}
}
} else {
d[a[i+1]+4-a[i]]++;
}
}
printf("%d\n",ans);
}
}