版权声明:欢迎转载,请注明出处,谢谢 https://blog.csdn.net/Dream_maker_yk/article/details/82757323
NOIP模拟 序列
题目:
思路:
我们考虑先计算出
的最少操作次数
很显然是
然后我们对这个数列c进行差分
然后就可以发现最后的答案是
这个结论比较显然
首先我们知道最后一个位置一定会被操作需要次数次,那么继续考虑
如果位置i比位置i+1要更大,显然这些操作次数是必须要加上的
如果i的操作次数比i+1要小,那么在i+1操作的时候i也可以被一起操作掉。
然后我们考虑怎么优化这个东西
我们考虑对一个区间加上的操作,我们只需要在数组c上面区间加上4,那么我们考虑这样加对差分数组p的实际影响,如果对
进行操作,那么差分后位置
,我们来讨论一下什么情况下答案会更小
当且仅当当前位置是 或者 ,所以直接对这个进行匹配,记录一下前缀的 和 的个数就好了,然后这题做完了
#include<bits/stdc++.h>
using namespace std;
#define fu(a,b,c) for(int a=b;a<=c;++a)
#define fd(a,b,c) for(int a=b;a>=c;--a)
#define N 100010
#define INF 0x3f3f3f3f
int n,a[N],b[N];
void solve(){
int cnt2=0,cnt3=0,ans=0;
scanf("%d",&n);
fu(i,1,n)scanf("%d",&a[i]);
fu(i,1,n)scanf("%d",&b[i]);
fu(i,1,n)a[i]=(b[i]-a[i]+4)%4;
fu(i,1,n)a[i]-=a[i+1];
fu(i,1,n)ans+=max(0,a[i]);
fu(i,1,n){
switch(a[i]){
case -2:{
if(cnt3)cnt3--,cnt2++,ans--;
break;
}
case -3:{
if(cnt3)cnt3--,ans-=2;
else if(cnt2)cnt2--,ans--;
break;
}
case 2:{cnt2++;break;}
case 3:{cnt3++;break;}
}
}
printf("%d\n",ans);
}
int main(){
int T;scanf("%d",&T);
while(T--)solve();
return 0;
}