BZOJ 4207 Can

青春壹個敷衍的年華 提交于 2019-11-30 19:48:28

题意:

因为是权贵提,就多挂了几个链接。

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));
  }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!