[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是答案区间的第一个和最后一个元素的下标。

输入示例


输出示例

Case #:
Case #:
Case #:
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,然后接着向左右扩展。

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

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 100010
int n, D, K, A[maxn][4], num[maxn<<2]; bool has[maxn<<2];
int al, ar;
bool can(int p) {
for(int i = 0; i < D; i++) if(has[A[p][i]]) return 1;
return 0;
}
void dfs(int l, int r, int ql, int qr, int k) {
while(l >= ql && can(l)) l--;
while(r <= qr && can(r)) r++;
// printf("dfs: %d %d\n", l, r);
int len = r - l - 1;
if(len > ar - al + 1) al = l + 1, ar = r - 1;
if(len == ar - al + 1 && l + 1 < al) al = l + 1, ar = r - 1;
if(k == K) return ;
if(l < ql && r > qr) return ;
for(int i = 0; i < D; i++) {
if(l >= ql) has[A[l][i]] = 1, dfs(l - 1, r, ql, qr, k + 1), has[A[l][i]] = 0;
if(r <= qr) has[A[r][i]] = 1, dfs(l, r + 1, ql, qr, k + 1), has[A[r][i]] = 0;
}
return ;
}
void solve(int l, int r) {
if(ar - al + 1 > r - l + 1 || l > r) return ;
int mid = l + r >> 1;
// printf("[%d, %d] %d\n", l, r, mid);
dfs(mid, mid, l, r, 0);
solve(l, mid - 1); solve(mid + 1, r);
return ;
} int main() {
int T = read();
for(int kase = 1; kase <= T; kase++) {
n = read(); D = read(); K = read();
int cnt = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < D; j++) num[++cnt] = A[i][j] = read();
sort(num + 1, num + cnt + 1);
for(int i = 0; i < n; i++)
for(int j = 0; j < D; j++) A[i][j] = lower_bound(num + 1, num + cnt + 1, A[i][j]) - num;
al = ar = 0;
solve(0, n - 1);
printf("Case #%d: %d %d\n", kase, al, ar);
} return 0;
}

[BZOJ4207]Can的更多相关文章

随机推荐

  1. SpringBoot 2.x (8):模板引擎

    SpringBoot中有很多的starter:本质是多个JAR包集合 比如我们常用的: <dependency> <groupId>org.springframework.bo ...

  2. JS进阶-特殊形式的函数-返回函数的函数/重写自己的函数

    返回函数的函数 // 返回函数的函数 function a() { alert("aa"); return function () { alert("bb"); ...

  3. idea 下maven 导入本地jar,以及导入之后 java不能引用问题

    1.在当前的项目中新建立一个lib文件夹,将需要导入的jar放入其中. 2.配置pom.xml 文件 <!--导入本地jar--> <dependency> <group ...

  4. c# sqlserver连接字符串

    odbc: string cnnstring = @"Driver={SQL Server Native Client 11.0};Initial Catalog = sxquadb;ser ...

  5. PHP实时输出内容到浏览器

    buffer buffer是一个内存地址空间,Linux系统默认大小一般为4096(4kb),即一个内存页.主要用于存储速度不同步的设备或者优先级不同的设备之间传办理数据的区域.通过buffer,可以 ...

  6. codevs 2046 孪生素数 3 (水题日常)

    时间限制: 1 s  空间限制: 32000 KB  题目等级 : 黄金 Gold 题目描述 Description 在质数的大家庭中,大小之差不超过2的两个质数称它俩为一对孪生素数,如2和3.3和5 ...

  7. Qt中常用的类

    QApplication 应用程序类                管理图形用户界面应用程序的控制流和主要设置 QLabel 标签类                                提供 ...

  8. 目标检测中bounding box regression

    https://zhuanlan.zhihu.com/p/26938549 RCNN实际包含两个子步骤,一是对上一步的输出向量进行分类(需要根据特征训练分类器):二是通过边界回归(bounding-b ...

  9. My Friends

    HMQ's blog RMY's blog Shq's blog wjyyy‘s blog

  10. python-opencv遍历图片像素,并对像素进行操作

    看代码: def access_pixels(frame): print(frame.shape) #shape内包含三个元素:按顺序为高.宽.通道数 height = frame.shape[0] ...