# | Time | Username | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
379554 | socho | Group Photo (JOI21_ho_t3) | C++14 | 5055 ms | 22612 KiB |
This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// upsolve, inspired by @smjleo code
#include <bits/stdc++.h>
using namespace std;
void fast() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
}
void ran() {
srand(chrono::steady_clock::now().time_since_epoch().count());
}
long long get_rand() {
long long a = rand();
long long b = rand();
return a * (RAND_MAX + 1ll) + b;
}
void usaco() {
freopen("problem.in", "r", stdin);
freopen("problem.out", "w", stdout);
}
template<typename T>
using min_pq = priority_queue<T, vector<T>, greater<T>>;
// #define endl '\n'
// #define double long double
// #define int long long
// const int MOD = 1000 * 1000 * 1000 + 7;
// const int MOD = 998244353;
const int MXN = 5005;
int n;
int arr[MXN];
int pos[MXN];
int dp[MXN];
vector<int> rgs;
int cost[MXN][MXN];
int iv[MXN][MXN];
int before[MXN];
int herepos[MXN];
int fw[MXN*2];
void update(int x, int v) {
for (; x<MXN*2; x+=x&(-x)) fw[x] += v;
}
int sum(int x) {
int res = 0;
for(; x; x-=x&(-x)) res += fw[x];
return res;
}
void solverow(int L) {
// only values >= L exist
// find all cost[L][x]
int curr = 0;
for (auto x: rgs) {
before[x] = curr;
curr++;
herepos[x] = curr;
}
memset(fw, 0, sizeof fw);
for (int x=L; x<=n; x++) {
// for each [L][x], how many inversions in this range?
// when i add a new x, the number of inversions increases by the number of values before x and smaller than x
// also increases by number of values after x and larger than x
iv[L][x] = iv[L][x-1];
// now i add item x
// all previous items which are before it are a new inversion
iv[L][x] += sum(pos[x]);
update(pos[x], 1);
}
memset(fw, 0, sizeof fw);
int tcost = 0;
for (int i=n; i>=L; i--) {
cost[L][i] = iv[L][i] + tcost;
tcost -= sum(before[i]+1);
update(before[i]+1, 1);
for (int x=before[i]; x<rgs.size(); x++) {
if (rgs[x] < i) tcost++;
}
/*
for (int x=before[i]; x>=0; x--) {
if (rgs[x] > i) tcost--;
}
*/
}
}
signed main() {
ran(); fast();
cin >> n;
for (int i=1; i<=n; i++) {
cin >> arr[i];
pos[arr[i]] = i;
}
for (int i=1; i<=n; i++) {
rgs.clear();
for (int j=1; j<=n; j++) {
if (arr[j] >= i) rgs.push_back(arr[j]);
}
solverow(i);
}
for (int i=1; i<=n; i++) {
// solve first i positions
dp[i] = INT_MAX / 2;
for (int j=1; j<=i; j++) {
// j..i are in reverse, + dp[j-1]
dp[i] = min(dp[i], dp[j-1] + cost[j][i]);
}
}
cout << dp[n] << endl;
}
Compilation message (stderr)
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
Fetching results... |