ABC102 C - Linear Approximation
問題概要
長さ N の整数列 A1,…,AN が与えられます。整数 b をいろいろ変えたときの
A1−(b+1) | + | A2−(b+1) | +⋯+ | AN−(b+N) |
の最小値を求めてください。
1≤N≤2×10の5乗
考えたこと
2次関数みたいなグラフになってると予想した。どっちかに動かせばどんどん小さくなるので、それを判定して出そうと思った。
途中で意味が分からなくなってあきらめた。
WAコード
#include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std; int N; int kaese(vector<int>A, int num) { int count = 0; int i = 0; while (1) { if (i == N) { break; } count += abs(A[i] - (num + i + 1)); i++; } return count; } int main() { cin >> N; vector<int>A(N); for (int i = 0; i < N; i++) { cin >> A[i]; } //どっち向きに動かすか決める bool canr = false; bool canl = false; int base = kaese(A, 0); if (base == kaese(A, 1)) { cout << base; } if (base < kaese(A, 1)) { canl = true; } if (base < kaese(A, -1)) { canr = true; } if (canl && canr) { cout << base; } if (canl) { int i = -2; int back = kaese(A, -1); while (1) { int j = kaese(A, i); if (back < j) { cout << back; return 0; } back = kaese(A, i); i--; } } if (canr) { int i = 2; int back = kaese(A, 1); while (1) { int j = kaese(A, i); if (back < j) { cout << back; return 0; } back = kaese(A, i); i++; } } }
参考
参考にさせて頂いたサイト
AtCoder ABC 102 C - Linear Approximation (ARC 100 C) (緑色, 300 点) - けんちょんの競プロ精進記録
まず、この [A-(b+1)]を変形して、分かりやすくすべき。
=>[x-Bi](Bi = Ai - i)
すると、|x−B1|+|x−B2|+⋯+|x−BN| となる
これはメディアンと呼ばれるもので、この形が出てきたら簡単に解けるらしい。
メディアンとは
中央値のこと。つまり、配列をsortし、その中央に出てきた値が、今回の答えだということ。
ACコード(けんちょんさん)
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int N; cin >> N; vector<long long> A(N), B(N); for (int i = 0; i < N; ++i) cin >> A[i], B[i] = A[i] - i; // メディアンを sort(B.begin(), B.end()); long long x = B[N/2]; // 答えを求める long long res = 0; for (int i = 0; i < N; ++i) { res += max(x - B[i], -x + B[i]); // |A| = max(A, -A) } cout << res << endl; }