快来踩爆这个蒟蒻吧|

Little_corn

园龄:1年1个月粉丝:11关注:17

2025-02-20 19:37阅读: 6评论: 0推荐: 0

ARC182D Increment Decrement Again

Solution

很好的 Ad-hoc!

首先发现这个取模非常难处理,那么不妨考虑先不取模,做完操作后再取模。那么限制相当于要求 |aiai+1|<m,且 ai,ai+1 两者的大小关系不变。这些显然是必要条件,同时我们断言,这些就是序列合法的充要条件。构造出一个合法的方案也很简单:首先不妨令 ai<ai+1,于是假设 ai<ai+1 向下一步一步调整即可,反之将 ai+1 向上调整,然后这样就会跳到最下面,由于两个东西的差 <m,因此不会跨过 ai 相同的模数。但是在 m=2 时向上和向下是一样的,因此不能调整,需要特判。

于是我们可以先令 a1=b1 ,根据上面的规则构造出一个合法的序列且与 b 同构。然后考虑操作次数,我们可以对 b 数组进行整体平移 kmk 是整数)。那么操作次数就是 i=1n|ai(ai+km)|。令 ci=aiai,根据小学知识,km 取到 c 的中位数两侧最优,直接算出来即可(没看懂 Wa90 的题解中为什么要二分)。

Code:

qwq
#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
const int N = 2e5 + 10;
int n, m, a[N], b[N], c[N];
ll solve(ll x){
ll ans = 0;
for(int i = 1; i <= n; i++) ans += abs(c[i] - x);
return ans;
}
int fl(int x, int y){
if(x >= 0) return (x / y);
else{
if(x % y) return (x / y - 1);
else return (x / y);
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) cin >> b[i];
if(m == 2){
for(int i = 1; i <= n; i++) if(a[i] != b[i]){cout << -1; return 0;}
cout << 0; return 0;
}
c[1] = b[1];
for(int i = 2; i <= n; i++){
int val = (b[i] - b[i - 1] + m) % m;
if(a[i] > a[i - 1]) c[i] = c[i - 1] + val;
else c[i] = c[i - 1] + val - m;
}
for(int i = 1; i <= n; i++) c[i] = a[i] - c[i];
sort(c + 1, c + n + 1); ll p = c[(n + 1) / 2];
cout << min(solve(fl(p, m) * m), solve((fl(p, m) + 1) * m));
return 0;
}

本文作者:Little_corn

本文链接:https://www.cnblogs.com/little-corn/p/18727540

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Little_corn  阅读(6)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起