#include <bits/stdc++.h> // Tomasz Nowak
using namespace std; // XIII LO Szczecin
using LL = long long; // Poland
#define FOR(i, l, r) for(int i = (l); i <= (r); ++i)
#define REP(i, n) FOR(i, 0, (n) - 1)
constexpr int inf = 0x3f3f3f3f;
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
vector<int> a(n);
for(int &ai : a) {
cin >> ai;
--ai;
}
vector<vector<bool>> normalgraph(n, vector<bool>(n)), antigraph = normalgraph;
REP(i, n)
FOR(j, i + 1, n - 1)
if(a[i] > a[j])
normalgraph[i][j] = normalgraph[j][i] = true;
else
antigraph[i][j] = antigraph[j][i] = true;
vector<int> antiperm = a;
REP(i, n)
antiperm[i] = n - 1 - a[i];
auto lis = [&](vector<int> &perm) {
vector<int> dp(n, 1);
REP(i, n)
REP(j, i)
if(perm[j] < perm[i])
dp[i] = max(dp[i], dp[j] + 1);
int i = int(max_element(dp.begin(), dp.end()) - dp.begin());
vector<int> ret = {i};
while(dp[i] > 1) {
int j = 0;
while(j < i and (dp[j] != dp[i] - 1 or perm[j] > perm[i]))
++j;
assert(j < i);
i = j;
ret.emplace_back(i);
}
reverse(ret.begin(), ret.end());
return ret;
};
vector<int> independent_normal = lis(a), independent_anti = lis(antiperm);
int s1 = int(independent_normal.size()), s2 = int(independent_anti.size());
int type = s1 < s2;
vector<int> independent = type ? independent_anti : independent_normal;
int indep_size = int(independent.size());
// cerr << indep_size << ' ';
vector<vector<bool>> graph = type ? antigraph : normalgraph;
vector<bool> inside_mask(n, true);
for(int v : independent)
inside_mask[v] = false;
vector<int> to_mask;
REP(v, n)
if(inside_mask[v])
to_mask.emplace_back(v);
int tm = int(to_mask.size());
vector<vector<LL>> dwumian(n + 1, vector<LL>(n + 1));
REP(i, n + 1)
dwumian[i][0] = dwumian[i][i] = 1;
FOR(i, 1, n)
FOR(j, 1, n)
dwumian[i][j] = dwumian[i - 1][j - 1] + dwumian[i - 1][j];
vector<pair<int, LL>> answer(n + 1, {inf, 0});
REP(mask, 1 << tm) {
int popc = __builtin_popcount(mask);
vector<int> inside;
inside.reserve(popc);
REP(i, tm)
if(mask & (1 << i))
inside.emplace_back(to_mask[i]);
int score = 0;
for(int i = 0; i < popc; ++i)
for(int j = i + 1; j < popc; ++j)
score += graph[inside[i]][inside[j]];
vector<int> contributon(indep_size);
for(int i = 0; i < popc; ++i)
for(int j = 0; j < indep_size; ++j)
if(graph[inside[i]][independent[j]])
++contributon[j];
vector<int> sorted(popc + 1);
for(int c : contributon)
++sorted[c];
vector<int> remaining = sorted;
int i = type ? popc : 0;
FOR(k, popc, popc + indep_size) {
if(k != popc) {
while(remaining[i] == 0) {
if(type == 0)
++i;
else
--i;
}
score += i;
--remaining[i];
}
if(type == 1)
score = k * (k - 1) / 2 - score;
if(answer[k].first > score) {
answer[k].first = score;
answer[k].second = dwumian[sorted[i]][remaining[i]];
}
else if(answer[k].first == score)
answer[k].second += dwumian[sorted[i]][remaining[i]];
if(type == 1)
score = k * (k - 1) / 2 - score;
}
}
FOR(i, 1, n)
cout << answer[i].first << ' ' << answer[i].second << '\n';
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | #include <bits/stdc++.h> // Tomasz Nowak using namespace std; // XIII LO Szczecin using LL = long long; // Poland #define FOR(i, l, r) for(int i = (l); i <= (r); ++i) #define REP(i, n) FOR(i, 0, (n) - 1) constexpr int inf = 0x3f3f3f3f; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n; cin >> n; vector<int> a(n); for(int &ai : a) { cin >> ai; --ai; } vector<vector<bool>> normalgraph(n, vector<bool>(n)), antigraph = normalgraph; REP(i, n) FOR(j, i + 1, n - 1) if(a[i] > a[j]) normalgraph[i][j] = normalgraph[j][i] = true; else antigraph[i][j] = antigraph[j][i] = true; vector<int> antiperm = a; REP(i, n) antiperm[i] = n - 1 - a[i]; auto lis = [&](vector<int> &perm) { vector<int> dp(n, 1); REP(i, n) REP(j, i) if(perm[j] < perm[i]) dp[i] = max(dp[i], dp[j] + 1); int i = int(max_element(dp.begin(), dp.end()) - dp.begin()); vector<int> ret = {i}; while(dp[i] > 1) { int j = 0; while(j < i and (dp[j] != dp[i] - 1 or perm[j] > perm[i])) ++j; assert(j < i); i = j; ret.emplace_back(i); } reverse(ret.begin(), ret.end()); return ret; }; vector<int> independent_normal = lis(a), independent_anti = lis(antiperm); int s1 = int(independent_normal.size()), s2 = int(independent_anti.size()); int type = s1 < s2; vector<int> independent = type ? independent_anti : independent_normal; int indep_size = int(independent.size()); // cerr << indep_size << ' '; vector<vector<bool>> graph = type ? antigraph : normalgraph; vector<bool> inside_mask(n, true); for(int v : independent) inside_mask[v] = false; vector<int> to_mask; REP(v, n) if(inside_mask[v]) to_mask.emplace_back(v); int tm = int(to_mask.size()); vector<vector<LL>> dwumian(n + 1, vector<LL>(n + 1)); REP(i, n + 1) dwumian[i][0] = dwumian[i][i] = 1; FOR(i, 1, n) FOR(j, 1, n) dwumian[i][j] = dwumian[i - 1][j - 1] + dwumian[i - 1][j]; vector<pair<int, LL>> answer(n + 1, {inf, 0}); REP(mask, 1 << tm) { int popc = __builtin_popcount(mask); vector<int> inside; inside.reserve(popc); REP(i, tm) if(mask & (1 << i)) inside.emplace_back(to_mask[i]); int score = 0; for(int i = 0; i < popc; ++i) for(int j = i + 1; j < popc; ++j) score += graph[inside[i]][inside[j]]; vector<int> contributon(indep_size); for(int i = 0; i < popc; ++i) for(int j = 0; j < indep_size; ++j) if(graph[inside[i]][independent[j]]) ++contributon[j]; vector<int> sorted(popc + 1); for(int c : contributon) ++sorted[c]; vector<int> remaining = sorted; int i = type ? popc : 0; FOR(k, popc, popc + indep_size) { if(k != popc) { while(remaining[i] == 0) { if(type == 0) ++i; else --i; } score += i; --remaining[i]; } if(type == 1) score = k * (k - 1) / 2 - score; if(answer[k].first > score) { answer[k].first = score; answer[k].second = dwumian[sorted[i]][remaining[i]]; } else if(answer[k].first == score) answer[k].second += dwumian[sorted[i]][remaining[i]]; if(type == 1) score = k * (k - 1) / 2 - score; } } FOR(i, 1, n) cout << answer[i].first << ' ' << answer[i].second << '\n'; } |
English