arc 043 c 題解
阿新 • • 發佈:2020-12-03
arc 043 c
若我們另外弄兩個陣列\(a'\)和\(b'\),其中\(a'[i]\)表示i在\(a\)中的位置,\(b'[i]\)表示i在b中的位置。
則転倒距離就是有多少對\((i,j)\)滿足\((i<j)\)且\(a'[i],a'[j]\)和\(b'[i]\)和\(b'[j]\)的大小關係不一樣。這樣就可以發現有解的充要條件就是\(A,B\)的転倒距離是偶數。
首先求転倒距離的方法比較簡單就是在A裡從前往後掃一遍,在B裡標記位置。用bit就可以了。
構造方法,我們在B中從前往後掃。若前面存在一些數在A中應該出現在當前數後面的數。若將這個移到前面去仍然小於等於應該交換的次數,就直接移動到這些數的前面。否則就移到一部分數的前面。
這樣,我們只需要對於一個數組,執行一系列操作: 將一個數向前移動x位。
我們可以對於第i個數記錄一個rank[i]表示第i個數在前i個的排名,從後往前還原即可。
sugim48
using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> i_i; typedef pair<ll, int> ll_i; typedef pair<double, int> d_i; typedef pair<ll, ll> ll_ll; typedef pair<double, double> d_d; struct edge { int u, v; ll w; }; ll MOD = 1000000007; ll _MOD = 1000000009; double EPS = 1e-10; struct bit { vector<ll> v; bit(int n) : v(n + 1) {} ll sum(int i) { ll res = 0; for (; i > 0; i -= i & -i) res += v[i]; return res; } void add(int i, ll x) { for (i++; i < v.size(); i += i & -i) v[i] += x; } }; int main() { int N; cin >> N; vector<int> A(N); for (int i = 0; i < N; i++) { cin >> A[i]; A[i]--; } vector<int> B(N); for (int i = 0; i < N; i++) { cin >> B[i]; B[i]--; } vector<int> a(N); for (int i = 0; i < N; i++) a[A[i]] = i; for (int i = 0; i < N; i++) B[i] = a[B[i]]; vector<int> hoge(N); for (int i = 0; i < N; i++) hoge[B[i]] = i; ll inv = 0; bit b(N); vector<int> unko(N); for (int i = 0; i < N; i++) { inv += i - b.sum(hoge[i]); unko[i] = i - b.sum(hoge[i]); b.add(hoge[i], 1); } if (inv % 2 == 1) { cout << -1 << endl; return 0; } inv /= 2; vector<int> ans(N); bit c(N); for (int i = N - 1; i >= 0; i--) { int k = min(inv, (ll)unko[i]); inv -= k; int t = i - unko[i] + k; int lb = 0, ub = N; while (ub - lb > 1) { int mid = (lb + ub) / 2; int x = mid - c.sum(mid); if (x <= t) lb = mid; else ub = mid; } c.add(lb, 1); ans[lb] = i; } for (int i = 0; i < N; i++) B[i] = A[ans[i]]; for (int i = 0; i < N; i++) cout << B[i] + 1 << (i + 1 < N ? ' ' : '\n'); }