P3543 [POI2012]WYR-Leveling Ground
- Update on 2022.9.29:修改表述。
- Update on 2025.1.22:修订。
P3543 [POI2012] WYR-Leveling Ground
区间操作转化为差分数组
首先考虑对每个差分值单独求解,解不定方程
先不考虑可行性。因为
当前
根据特解的形式
当
容易证明调整一个数的代价随着调整次数增加仅在
一个神奇的性质是
忽略问题限制得到基本解法再调整,巧妙结合反悔贪心和扩展欧几里得。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define TIME 1e3 * clock() / CLOCKS_PER_SEC
using ll = long long;
using uint = unsigned int;
// using lll = __int128;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using ull = unsigned long long;
inline ll read() {
ll x = 0, sgn = 0;
char s = getchar();
while(!isdigit(s)) sgn |= s == '-', s = getchar();
while(isdigit(s)) x = x * 10 + s - '0', s = getchar();
return sgn ? -x : x;
}
inline void print(ll x) {
if(x < 0) return putchar('-'), print(-x);
if(x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
bool Mbe;
constexpr int N = 1e5 + 5;
constexpr ll INF = 0x3f3f3f3f3f3f3f3f;
int n, a, b, c[N], d, ad, bd;
ll u, v, x[N], y[N], dx, ans;
int sgn(ll x) {return x < 0 ? -1 : 1;}
void exgcd(ll a, ll b, ll &x, ll &y) {
if(!b) return x = 1, y = 0, void();
exgcd(b, a % b, y, x), y -= a / b * x;
}
priority_queue<pii, vector<pii>, greater<pii>> q;
void ins(int i) {q.push({abs(x[i] - sgn(dx) * bd) + abs(y[i] + sgn(dx) * ad) - abs(x[i]) - abs(y[i]), i});}
bool Med;
int main() {
fprintf(stderr, "%.3lf MB\n", (&Mbe - &Med) / 1048576.0);
#ifdef ALEX_WEI
FILE* IN = freopen("1.in", "r", stdin);
FILE* OUT = freopen("1.out", "w", stdout);
#endif
cin >> n >> a >> b, d = __gcd(a, b);
ad = a / d, bd = b / d, exgcd(a, b, u, v);
for(int i = 1; i <= n; i++) c[i] = read();
for(int i = ++n; i; i--) c[i] -= c[i - 1], x[i] = INF;
for(int i = 1; i <= n; i++) {
if(c[i] % d) puts("-1"), exit(0);
ll p = u * c[i] / d, q = v * c[i] / d, _x, _y;
auto chk = [&]() {if(abs(_x) + abs(_y) < abs(x[i]) + abs(y[i])) x[i] = _x, y[i] = _y;};
_x = (p % bd + bd) % bd, _y = (c[i] - _x * a) / b, chk(), _x -= bd, _y += ad, chk();
_y = (q % ad + ad) % ad, _x = (c[i] - _y * b) / a, chk(), _y -= ad, _x += bd, chk();
dx += x[i], ans += abs(x[i]) + abs(y[i]);
}
for(int i = 1; i <= n; i++) ins(i);
for(ll i = 0; i < abs(dx); i += bd) {
pii t = q.top(); q.pop();
ans += t.fi, x[t.se] -= sgn(dx) * bd, y[t.se] += sgn(dx) * ad, ins(t.se);
}
cout << ans / 2 << "\n";
cerr << TIME << " ms\n";
return 0;
}
/*
2022/9/29
author: Alex_Wei
start coding at 19:23
finish debugging at 20:07
*/