jzoj4788 序列

题目

给定序列A,B,每一次操作可以让A的i~j这个区间内+1%4,求多少次操作才能让A达到B

先求出对于第i个位置从Ai>Bi要做多少次,记作Di
如果不考虑模的话,这题就是一个经典的粉刷问题,
Ans=DiDi1|(Di>Di1)
然后我们再考虑模,如果操作次数+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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值