标签:cas 存在 选择 color sort turn r++ while lap
[BZOJ4207]Can
试题描述
输入
输出
对于每个case,输出一行,"Case #x: y z",x表示case标号(从1开始),y和z是答案区间的第一个和最后一个元素的下标。
输入示例
4 8 1 2 1 2 3 2 4 5 4 6 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 6 2 3 10 20 50 60 70 30 40 40 30 30 20 40 10 1 3 2 4 3 1 4 5 3 1 1 2
输出示例
Case #1: 1 3 Case #2: 0 1 Case #3: 1 5 Case #4: 1 4
数据规模及约定
题解
这是一道分治 + 暴搜的好题。
做法是这样的,我们在分治时考虑每次分治跨中点的部分,可以从中点开始向两边扩展,一旦遇到当前选的 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; }
标签:cas 存在 选择 color sort turn r++ while lap
原文地址:http://www.cnblogs.com/xiao-ju-ruo-xjr/p/6323637.html