1. 程式人生 > >【LOJ2323】「清華集訓 2017」小 Y 和地鐵

【LOJ2323】「清華集訓 2017」小 Y 和地鐵

【題目連結】

【思路要點】

  • 很不錯的腦洞題。
  • 附上官方題解。
    官方題解
    官方題解
  • 時間複雜度 O ( T 2
    N 2 ) O(T*2^{\frac{N}{2}})

【程式碼】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 105; const int INF = 1e9; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void
read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, ans, a[MAXN], b[MAXN], last[MAXN]; int cntup, up[MAXN], cntdown, down[MAXN]; void work(int pos, int sum) { if (sum >= ans) return; if (pos > n) { ans = sum; return; } if (a[pos] == 0) work(pos + 1, sum); else { int cnt = 0, cmt = 0; for (int i = 1; i <= cntup; i++) { cnt += pos <= up[i] && a[pos] >= up[i]; cmt += a[pos] <= up[i]; } for (int i = 1; i <= cntdown; i++) cmt += pos <= down[i]; up[++cntup] = a[pos]; work(pos + 1, sum + min(cnt, cmt)); cntup--, cnt = 0, cmt = 0; for (int i = 1; i <= cntdown; i++) { cnt += pos <= down[i] && a[pos] >= down[i]; cmt += a[pos] <= down[i]; } for (int i = 1; i <= cntup; i++) cmt += pos <= up[i]; down[++cntdown] = a[pos]; work(pos + 1, sum + min(cnt, cmt)); cntdown--; } } int main() { int T; read(T); while (T--) { read(n); memset(last, 0, sizeof(last)); ans = INF; for (int i = 1; i <= n; i++) { read(b[i]), a[i] = 0; a[last[b[i]]] = i; last[b[i]] = i; } work(1, 0); printf("%d\n", ans); } return 0; }