CF1605E Array Equalizer
Array Equalizer
题面描述
Jeevan 有两个长度为
- 选择一个
( ),对所有满足 并且 的 ,令 。 - 选择一个
( ),对所有满足 并且 的 ,令 。
不幸的是,他忘记了
- 如果
,那么把 变为 至少需要几次操作?
Solution
题目没有要求判断无解,那么先想如何构造一种通解。考虑枚举每次修改的起始位置(即每次修改的
令
因为每次修改影响的是
移项得:
用迪利克雷卷积来表示就是
将
答案显然是
由于存在绝对值,因此考虑讨论
- 当
时, 与 无关,可以预处理直接算出。 - 当
或 时,将 排序,那么所有 的 是一个前缀, 的 是一个后缀,因此直接二分找到分界点即可。
总时间复杂度为
Code
// Cirno is not baka!
#include <bits/stdc++.h>
#define For(i, a, b) for (int i = (a); i <= (int)(b); ++i)
#define Rof(i, a, b) for (int i = (a); i >= (int)(b); --i)
#define FILE(filename) { \
freopen(#filename ".in", "r", stdin); \
freopen(#filename ".out", "w", stdout); \
}
#define All(x) x.begin(), x.end()
#define rAll(x) x.rbegin(), x.rend()
#define pii pair<int, int>
#define fi first
#define se second
#define i64 long long
#define mkp make_pair
#define int long long
#define epb emplace_back
#define pb push_back
using namespace std;
const int _N = 2e5 + 5, mod = 1e9 + 7, inf = 1e9;
template<typename T> void Max(T &x, T y) {x = max(x, y);}
template<typename T> void Min(T &x, T y) {x = min(x, y);}
namespace BakaCirno {
int N, M, A[_N], B[_N];
bitset<_N> flag;
vector<int> prim;
int mu[_N];
void InitPrime(int n) {
mu[1] = 1;
For(i, 2, n) {
if (!flag[i]) {
prim.epb(i);
mu[i] = -1;
}
for (int j : prim) {
if (i * j > n) break;
flag[i * j] = 1;
if (i % j == 0) {mu[i * j] = 0; break;}
mu[i * j] = -mu[i];
}
}
}
int val[_N];
int t1[_N], tot1, t2[_N], tot2, sum3;
int pre1[_N], pre2[_N], suf1[_N], suf2[_N];
void Init() {
InitPrime(N);
For(i, 2, N) for (int j = i; j <= N; j += i)
val[j] += mu[j / i] * (A[i] - B[i]);
For(i, 2, N) {
if (mu[i] == 0) sum3 += abs(val[i]);
if (mu[i] == 1) t1[++tot1] = val[i];
if (mu[i] == -1) t2[++tot2] = val[i];
}
sort(t1 + 1, t1 + tot1 + 1), sort(t2 + 1, t2 + tot2 + 1);
For(i, 1, tot1) pre1[i] = pre1[i - 1] + t1[i];
For(i, 1, tot2) pre2[i] = pre2[i - 1] + t2[i];
Rof(i, tot1, 1) suf1[i] = suf1[i + 1] + t1[i];
Rof(i, tot2, 1) suf2[i] = suf2[i + 1] + t2[i];
}
int Solve(int x) {
int res = sum3 + abs(A[1] - x), L, R;
L = 1, R = tot1;
while (L <= R) {
int mid = (L + R) >> 1;
if (t1[mid] + A[1] - x >= 0) R = mid - 1;
else L = mid + 1;
}
res += (x - A[1]) * R - pre1[R] + suf1[L] + (tot1 - L + 1) * (A[1] - x);
L = 1, R = tot2;
while (L <= R) {
int mid = (L + R) >> 1;
if (t2[mid] - A[1] + x >= 0) R = mid - 1;
else L = mid + 1;
}
res += (A[1] - x) * R - pre2[R] + suf2[L] - (tot2 - L + 1) * (A[1] - x);
return res;
}
void _() {
cin >> N;
For(i, 1, N) cin >> A[i];
For(i, 1, N) cin >> B[i];
Init();
cin >> M;
For(i, 1, M) {
int x; cin >> x;
cout << Solve(x) << '\n';
}
}
}
signed main() {
// FILE(test);
cin.tie(0)->sync_with_stdio(0); int T = 1;
// cin >> T;
while (T--) BakaCirno::_();
// fout.flush();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步