正题
题目大意
一个序列AAA可以每次选择一段区间(Ai+1)%4(i∈[l..r])(A_{i}+1)\%4(i\in [l..r])(Ai+1)%4(i∈[l..r])。求最少次数使其变成BBB序列。
解题思路
先计算出每个数字最少加多少可以变成目标数字记录入aaa数组。
然后若不考虑一个数要取模多次的话答案就是
∑i=1nmax{ai−ai−1,0}(a0=0)\sum_{i=1}^n \max\{a_i-a_{i-1},0\}(a_{0}=0)i=1∑nmax{ai−ai−1,0}(a0=0)
但是这道题变成了每个柱子的高度是4ki+ai(k∈N)4k_{i}+a_{i}(k\in \mathbb{N})4ki+ai(k∈N)
那么我们考虑若一段区间[l..r][l..r][l..r]的kkk要加1会更优那么有
al−al−1+4<ar+1−ara_{l}-a_{l-1}+4<a_{r+1}-a_{r}al−al−1+4<ar+1−ar
那么答案就可以减去(ar+1−ar)−(al−al−1+4)(a_{r+1}-a_{r})-(a_{l}-a_{l-1}+4)(ar+1−ar)−(al−al−1+4)
那么我们枚举rrr,开个桶来计算lll
codecodecode
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=101000;
int T,n,a[N],ans=2147483647,t[5];
int main()
{scanf("%d",&T);while(T--){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);memset(t,0,sizeof(t));ans=0;for(int i=1;i<=n;i++){int val;scanf("%d",&val);a[i]=(val-a[i]+4)%4;ans+=max(a[i]-a[i-1],0);}for(int i=2;i<=n;i++){int c=a[i]-a[i-1];if(c>0){if(t[1]&&c>1) t[1]--,t[c]++,ans-=c-1;else if(t[2]&&c>2) t[2]--,t[c]++,ans-=c-2; }else t[c+4]++;}printf("%d\n",ans);}
}