[BZOJ4207]Can

试题描述

这个问题是源于一个在棋盘上玩的,由Sid Sackson设计的名叫Can't stop的游戏的。这个问题与Can't stop有一定的相似之处,但是不需要玩过Can't stop。
你在玩一个(非常大型的)棋盘游戏。在这个游戏里面,给出了一个长度为N的roll set的序列。每个roll set包括D个die roll,每个die roll是一个正整数。
你需要找到序列中总长度最大的极好的区间。区间即为连续的一段roll set。如果存在k个数使某个区间内的所有roll set都至少包含其中一个,那么,这个区间就被认为是极好的。
例如:d=2,k=3时,roll set如下:
 
Set 0: 10 20
Set 1: 50 60
Set 2: 70 30
Set 3: 40 40
Set 4: 30 30
Set 5: 20 40
从0到2的区间是极好的,因为从0到2中的每个roll set都包含了10,50或70 。从1到5的区间也是极好的,因为1到5的所有roll set都包含50,30或40。它包含了5个roll set,是总长度最大的极好的区间。
你的任务是输出总长度最大的极好的区间的第一个元素的下标和最后一个元素的下标。如果有多个长度一样的,输出第一个元素下标最小的。请注意下标从0开始。

输入

第一行包含一个整数T,表示数据组数。接下来T组数据。
每组数据的第一行是三个正整数N,D,k,描述如上。接下来一行,包含N*D个整数,前D个整数表示第一个roll set ,接下来D个表示第二个roll set,以此类推。

输出

对于每个case,输出一行,"Case #x: y z",x表示case标号(从1开始),y和z是答案区间的第一个和最后一个元素的下标。

输入示例

  1.  

输出示例

  1. Case #:
  2. Case #:
  3. Case #:
  4. Case #:

数据规模及约定

对于45%的数据,N<=1000
对于50%的数据,k=2
前两部分数据共计70%
对于100%的数据,2<=k<=3
输入文件在4.8M以内
T=10.
1 ≤ D ≤ 4.
1 ≤ 每个die roll ≤ 10^5.
对于最多6个case, 1 ≤ N ≤ 10^5.
对于其他所有的case, 1 ≤ N ≤ 10^3.

题解

这是一道分治 + 暴搜的好题。

做法是这样的,我们在分治时考虑每次分治跨中点的部分,可以从中点开始向两边扩展,一旦遇到当前选的 k’ 个数不能搞掉的 roll set,就枚举一下选择这个 roll set 中的哪一个 die roll,然后接着向左右扩展。

最优性剪枝能剪掉不少情况。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cmath>
  5. #include <stack>
  6. #include <vector>
  7. #include <queue>
  8. #include <cstring>
  9. #include <string>
  10. #include <map>
  11. #include <set>
  12. using namespace std;
  13.  
  14. const int BufferSize = 1 << 16;
  15. char buffer[BufferSize], *Head, *Tail;
  16. inline char Getchar() {
  17. if(Head == Tail) {
  18. int l = fread(buffer, 1, BufferSize, stdin);
  19. Tail = (Head = buffer) + l;
  20. }
  21. return *Head++;
  22. }
  23. int read() {
  24. int x = 0, f = 1; char c = Getchar();
  25. while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
  26. while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
  27. return x * f;
  28. }
  29.  
  30. #define maxn 100010
  31. int n, D, K, A[maxn][4], num[maxn<<2];
  32.  
  33. bool has[maxn<<2];
  34. int al, ar;
  35. bool can(int p) {
  36. for(int i = 0; i < D; i++) if(has[A[p][i]]) return 1;
  37. return 0;
  38. }
  39. void dfs(int l, int r, int ql, int qr, int k) {
  40. while(l >= ql && can(l)) l--;
  41. while(r <= qr && can(r)) r++;
  42. // printf("dfs: %d %d\n", l, r);
  43. int len = r - l - 1;
  44. if(len > ar - al + 1) al = l + 1, ar = r - 1;
  45. if(len == ar - al + 1 && l + 1 < al) al = l + 1, ar = r - 1;
  46. if(k == K) return ;
  47. if(l < ql && r > qr) return ;
  48. for(int i = 0; i < D; i++) {
  49. if(l >= ql) has[A[l][i]] = 1, dfs(l - 1, r, ql, qr, k + 1), has[A[l][i]] = 0;
  50. if(r <= qr) has[A[r][i]] = 1, dfs(l, r + 1, ql, qr, k + 1), has[A[r][i]] = 0;
  51. }
  52. return ;
  53. }
  54. void solve(int l, int r) {
  55. if(ar - al + 1 > r - l + 1 || l > r) return ;
  56. int mid = l + r >> 1;
  57. // printf("[%d, %d] %d\n", l, r, mid);
  58. dfs(mid, mid, l, r, 0);
  59. solve(l, mid - 1); solve(mid + 1, r);
  60. return ;
  61. }
  62.  
  63. int main() {
  64. int T = read();
  65. for(int kase = 1; kase <= T; kase++) {
  66. n = read(); D = read(); K = read();
  67. int cnt = 0;
  68. for(int i = 0; i < n; i++)
  69. for(int j = 0; j < D; j++) num[++cnt] = A[i][j] = read();
  70. sort(num + 1, num + cnt + 1);
  71. for(int i = 0; i < n; i++)
  72. for(int j = 0; j < D; j++) A[i][j] = lower_bound(num + 1, num + cnt + 1, A[i][j]) - num;
  73. al = ar = 0;
  74. solve(0, n - 1);
  75. printf("Case #%d: %d %d\n", kase, al, ar);
  76. }
  77.  
  78. return 0;
  79. }

[BZOJ4207]Can的更多相关文章

随机推荐

  1. (020)[虚拟系统]Win7网络连接红叉(无解决)

    该虚拟机在重装主系统前是可以连接网络的,主系统重新安装以后,导入新安装的VM以后,网络图标显示红叉. 查看设备管理,显示没有安装以太网驱动. 重新安装 Vmware Tools,未果.VMware官网 ...

  2. 关于发布WP 8.1应用信息不匹配问题的解决办法

    错误提示:   与此更新关联的程序包标识符与已上传程序包中的标识符不匹配: The package identity associated with this update doesn't match ...

  3. 微服务熔断限流Hystrix之流聚合

    简介 上一篇介绍了 Hystrix Dashboard 监控单体应用的例子,在生产环境中,监控的应用往往是一个集群,我们需要将每个实例的监控信息聚合起来分析,这就用到了 Turbine 工具.Turb ...

  4. AJPFX简述Java中this关键字的使用

    Java中this关键字的使用主要有两处: 1.构造方法 this指的是调用构造方法进行初始化的对象. //有参构造public Human(String name, int age) { this( ...

  5. PKU_campus_2018_D Chocolate

    思路: 题目链接http://poj.openjudge.cn/practice/C18D/ kruskal过程中使用乘法原理计数. 实现: #include <bits/stdc++.h> ...

  6. EventBus 报“Subscriber class already registered to event class”错误

    这句子的话意思也很容易理解,“接收者类已经被注册为事件类了”. 之前我是这么写: 事件注册是写在onStart()里面的 @Override protected void onStart() { su ...

  7. ubuntu下安装mongo扩展

    安装openssl apt-get install openssl libssl-dev libssl0.9.8 libgtk2.0-dev 安装php-pear apt-get install ph ...

  8. .NET多线程总结

    1.不需要传递参数,也不需要返回参数 我们知道启动一个线程最直观的办法是使用Thread类,具体步骤如下: public void test() { ThreadStart threadStart = ...

  9. while循环(break、continue)

    while循环 流程:判断条件是否为真,如果条件为真,执行代码块,然后再次判断条件是否为真,如果为真,执行代码块,直到条件判断为假,结束循环 格式 while  条件: 代码块(循环体) else:- ...

  10. Qt 之 QApplication

    1.QApplication QApplication类管理GUI程序的控制流和主要设置,是基于QWidget的,为此特化了QGuiApplication的一些功能,处理QWidget特有的初始化和结 ...