题意:
因为是权贵提,就多挂了几个链接。
https://bzoj.zcmimi.tk/p/4207.html
https://www.lydsy.com/JudgeOnline/problemset.php
Sol:
要求最长? 看起来不太好做,不过d和k很小,于是考虑暴力。
找子区间要想分治吧,考虑当前分治中心为MID(强制跨过MID)
然后暴力往两边扩展,加个最优性剪枝就过了。
复杂度$O(Tn\log n\times d^k\times 2^k)$
#include<cstdio> #include<cstring> #define R register const int N = 1e5+7; int A[6][N], vis[N*10], n, d, k, ansl, ansr; inline int check(int omg) { for (int i = 1; i <= d; i++) if (vis[A[i][omg]]) return 1; return 0; } void dfs(int l, int r, int lx, int rx, int K) { while (check(l - 1) && l > lx) l--; while (check(r + 1) && r < rx) r++; if (r - l > ansr - ansl) ansl = l, ansr = r; if (r - l == ansr - ansl && l < ansl) ansl = l, ansr = r; if (k == K) return; for (int i = 1; i <= d; i++) { if (l != lx) vis[A[i][l - 1]] = 1, dfs(l - 1, r, lx, rx, K + 1), vis[A[i][l - 1]] = 0; if (r != rx) vis[A[i][r + 1]] = 1, dfs(l, r + 1, lx, rx, K + 1), vis[A[i][r + 1]] = 0; } } void solve(int l, int r) { if ((r - l < ansr - ansl) || l > r) return; int MID = (l + r) >> 1; for (int i = 1; i <= d; i++) vis[A[i][MID]] = 1, dfs(MID, MID, l, r, 1), vis[A[i][MID]] = 0; solve(l, MID - 1), solve(MID + 1, r); } int main() { int T, idt = 0; scanf("%d", &T); while (T--) { idt++; ansl = 1, ansr = 1; scanf("%d%d%d", &n, &d, &k); for (R int i = 1; i <= n; i++) for (R int j = 1; j <= d; j++) scanf("%d", &A[j][i]); solve(1, n); printf("Case #%d: %d %d\n", idt, ansl - 1, ansr - 1); memset(A, 0, sizeof(A)); } }