*题解:[ABC467E] Adjacent Sums (hard)
解析
不难发现,只要确定某个 \(A_i\),那么其它的 \(A_j\) 也能唯一确定。不妨尝试确定 \(A_1\),考虑 \(A_1 \leftarrow A_1 + 1\) 对答案带来的影响。记 \(A'_i\) 表示不对 \(A_1\) 进行操作,为使得序列合法,在模 \(M\) 意义下\(A_i\) 需要达到的值,也就是说 \(A'_i = B_{i - 1} - A'_{i - 1}\)。每当 \(A'_1 \leftarrow A'_1 + 1\),由于需要有 \(A'_1 + A'_2 \equiv B_1\),因此需要令 \(A'_2 \leftarrow A'_2 - 1\);由于需要有 \(A'_2 + A'_3 \equiv B_2\),因此需要令 \(A'_3\leftarrow A'_3 + 1\)。依此类推,规律是奇数位置 \(+1\),偶数位置 \(-1\)。
答案即为:
其中 \(x=A'_1 - A_1\)。对于每次 \(A'_1 \leftarrow A'_1 + 1\) 即 \(x' \leftarrow x + 1\) 的操作,奇数位置 \(i\) 上的值变为 \((A'_i+x-A_i + 1) \bmod M\),此次操作所做的贡献当 \((A'_i + x' - A_i) \equiv 0\) 时为 \(-M\),其余情况时为 \(1\)。偶数位置上同理,当 \((A'_i - x' - A_i) \equiv M-1\) 时,做的贡献为 \(M\),其余情况为 \(-1\)。由于奇数位置个数不少于偶数位置个数,所以通常情况下 \(x \leftarrow x + 1\) 会使得答案 \(+1\) 或者不变,在一些情况下可能会使得答案减少(如上文所描述的奇数位置上的特殊贡献),故只需统计使得某个 \(i\) 满足 \((A'_i + x - A_i) \equiv 0\) 且 \(2 \nmid i\) 的所有 \(x\) 对应的答案。
为了统计,我们还要对偶数位置求满足 \((A'_i - x' - A_i) \equiv M-1\) 的 \(x\) 以处理这些位置上的特殊贡献。
实现上,需要 \(O(n)\) 求出所有 \(x\),将其排序并依次统计。时间复杂度 \(O(n \log n)\)。
代码
/*
*/
#include <bits/stdc++.h>
#define eps 0.0000000001
using namespace std;
typedef long long ll;
typedef unsigned ui;
typedef pair<ll, ll> pii;
const int N = 2e5 + 5, M = 200000 + 5, P = 450, mod = 1e9 + 7, mod2 = 1e9 + 7, b1 = 131;
int a[N],b[N],a1[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<n;i++){
cin>>b[i];
}
ll cnt = 0,res = 9e18;
a1[1] = a[1];
for(int i=2;i<=n;i++){
a1[i] = ((b[i - 1] - a1[i - 1]) % m + m) % m;
cnt += ((a1[i] - a[i]) % m + m) % m;
}
vector<pii> v;
for(int i=1;i<=n;i++){
int x;
if(i & 1){
x = ((a[i] - a1[i]) % m + m) % m;
}else{
x = ((a1[i] - a[i] + 1) % m + m) % m;
}
if(!x) x += m;//特殊贡献对应的 x 必须有前驱
v.push_back({x,i % 2 == 0 ? m : - m});
}
sort(v.begin(),v.end());
int l = 0,r = 0,last = 0;
while(r < v.size()){
while(r < v.size() && v[l].first == v[r].first){
cnt += v[r].second;
r++;
}
cnt += (v[l].first - last) * (n % 2 != 0);
res = min(cnt,res);
last = v[l].first;
l = r;
}
cout<<res;
return 0;
}

浙公网安备 33010602011771号