[BZOJ3535][Usaco2014 Open]Fair Photography

试题描述

FJ's N cows (1 <= N <= 100,000) are standing at various positions along a long one-dimensional fence. The ith cow is standing at position x_i (an integer in the range 0...1,000,000,000) and has breed b_i (an integer in the range 1..8). No two cows occupy the same position. FJ wants to take a photo of a contiguous interval of cows for the county fair, but we wants all of his breeds to be fairly represented in the photo. Therefore, he wants to ensure that, for whatever breeds are present in the photo, there is an equal number of each breed (for example, a photo with 27 each of breeds 1 and 3 is ok, a photo with 27 of breeds 1, 3, and 4 is ok, but 9 of breed 1 and 10 of breed 3 is not ok). Farmer John also wants at least K (K >= 2) breeds (out of the 8 total) to be represented in the photo. Help FJ take his fair photo by finding the maximum size of a photo that satisfies FJ's constraints. The size of a photo is the difference between the maximum and minimum positions of the cows in the photo. If there are no photos satisfying FJ's constraints, output -1 instead.

X的非负轴上有n头奶牛,每个奶牛有一个坐标xi和品种bi.
没有两头奶牛在同一个位置上.
选择一个区间[L,R],使得所有品种的奶牛数量, 在[L,R]中,要么为0,要么相等.且出现的品种数(注意是品种数而不是每个品种的个数丫> <.)至少为K.
区间长度定义为[L,R]中最右和最左的奶牛的差的绝对值.
求最长满足上述条件的区间长度.

输入

* Line 1: N and K separated by a space
* Lines 2..N+1: Each line contains a description of a cow as two integers separated by a space; x(i) and its breed id.

输出

* Line 1: A single integer indicating the maximum size of a fair photo. If no such photo exists, output -1. 

输入示例


输出示例


数据规模及约定

见“试题描述

题解

其实这题唯一用到的数据结构就是哈希表(数组啥的就暂且不算数据结构了)。

我们发现颜色种类很少,那么突破口一定在这里。

考虑一种更简单的情况:颜色只有两种的时候怎么做。不难联想到类似“括号序列”的做法,左括号 +1,右括号 -1;在这里就是颜色 1 的位置上 +1,颜色 2 的位置上 -1。

好了,有了上面做法的启发,我们可以拓展到颜色不多的做法了。深度理解一下一堆 +1、-1 的意义是什么:每个位置上的数其实就是颜色 1 比颜色 2 多了多少个。

那么最多 8 种颜色,我们 28 枚举一下选且只选的颜色集合 S。那么对于不在集合 S 的颜色的位置就把它删掉,这样会把整个序列分成若干个连续的区间,区间总长度不超过 O(n)。对于每一段区间我们这样处理:在每个位置上记录“考虑以这个位置为结尾的前缀中集合 S 中所有颜色的个数比集合 S 中第一个颜色的个数多多少”,然后如果有两个位置上的这样的信息完全相同则表明所有出现的颜色数目相等。于是我们每个位置上的信息哈希一下,并存储信息最早出现的位置,然后随便统计一下答案就好了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std; 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
#define oo 2147483647 struct Cow {
int x, b;
Cow() {}
Cow(int _, int __): x(_), b(__) {}
bool operator < (const Cow& t) const { return x < t.x; }
} cs[maxn];
int n, K; #define MOD 2097151
bool Equal(int a[8], int b[8]) {
for(int i = 0; i < 8; i++) if(a[i] != b[i]) return 0;
return 1;
}
int CNT;
struct Hash {
int ToT, head[MOD+1], nxt[maxn], more[maxn][8], val[maxn]; void init() {
for(int t = 1; t <= ToT; t++) {
int u = 0;
for(int i = 0; i < 8; i++) CNT++, u = u ^ more[t][i] & MOD;
head[u] = 0;
}
ToT = 0;
return ;
} int Find(int tmp[8]) {
int u = 0;
for(int i = 0; i < 8; i++) u = u ^ tmp[i] & MOD;
for(int e = head[u]; e; e = nxt[e]) if(Equal(more[e], tmp)) return val[e];
return oo;
}
void Insert(int tmp[8], int v) {
int u = 0;
for(int i = 0; i < 8; i++) u = u ^ tmp[i] & MOD;
val[++ToT] = v; for(int i = 0; i < 8; i++) more[ToT][i] = tmp[i]; nxt[ToT] = head[u]; head[u] = ToT;
return ;
}
} hh; int lstb[maxn][8], more[maxn][8], ans = -1;
void work(int S) {
int lCNT = CNT;
memset(more, 0, sizeof(more));
int cnt[8], mb;
for(int i = 0; i < 8; i++) if(S >> i & 1){ mb = i; break; }
bool has = 0;
for(int i = 1; i <= n;) {
while(i <= n && !(S >> cs[i].b & 1)) i++;
if(i > n) break; memset(cnt, 0, sizeof(cnt));
hh.init(); hh.Insert(cnt, i - 1);
int l = i, r = i;
while(r <= n && (S >> cs[r].b & 1)) {
cnt[cs[r].b]++;
for(int j = 0; j < 8; j++) {
if(S >> j & 1) more[r][j] = cnt[j] - cnt[mb];
CNT++;
}
if(hh.Find(more[r]) == oo) hh.Insert(more[r], r);
r++;
}
r--;
for(int p = l; p <= r; p++) {
int pre = hh.Find(more[p]) + 1; bool ok = 1;
for(int j = 0; j < 8; j++) {
CNT++;
if((S >> j & 1) && lstb[p][j] < pre){ ok = 0; break; }
}
if(ok) has = 1, ans = max(ans, cs[p].x - cs[pre].x);
}
i = r + 1;
}
// printf("work(%d) %d %d\n", S, CNT, CNT - lCNT);
return ;
} int main() {
n = read(); K = read();
for(int i = 1; i <= n; i++) {
int x = read(), b = read() - 1;
cs[i] = Cow(x, b);
} sort(cs + 1, cs + n + 1);
int lst[8]; memset(lst, 0, sizeof(lst));
for(int i = 1; i <= n; i++) {
lst[cs[i].b] = i;
for(int j = 0; j < 8; j++) lstb[i][j] = lst[j];
}
int all = (1 << 8) - 1;
for(int S = 0; S <= all; S++) {
int cnt = 0;
for(int i = 0; i < 8; i++) cnt += S >> i & 1;
if(cnt >= K) work(S);
} printf("%d\n", ans); return 0;
}

[BZOJ3535][Usaco2014 Open]Fair Photography的更多相关文章

  1. BZOJ3540: [Usaco2014 Open]Fair Photography

    3540: [Usaco2014 Open]Fair Photography Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 72  Solved: 29 ...

  2. bzoj 3540: [Usaco2014 Open]Fair Photography

    3540: [Usaco2014 Open]Fair Photography Description FJ's N cows (2 <= N <= 100,000) are standin ...

  3. [Usaco2014 Open]Gold Fair Photography(hash)

    最近做了usaco2014 open的金组,果然美帝的题还是没有太简单啊QAQ,被每年的月赛骗了QAQ 不过话说官方题解真心棒(虽然英文的啃得好艰难,我英语渣你们别鄙视我= =),标程超级优美QAQ ...

  4. P3105 [USACO14OPEN]公平的摄影Fair Photography

    题意翻译 在数轴上有 NNN 头牛,第 iii 头牛位于 xi(0≤xi≤109)x_i\:(0\le x_i\le 10^9)xi​(0≤xi​≤109) .没有两头牛位于同一位置. 有两种牛:白牛 ...

  5. Fair Photography

    题目大意: 给出直线上N个点的位置和颜色(0或1),求最大的区间,使得区间内0的个数大于等于1的个数且0的个数减去1的个数为偶数. 解题过程: 1.先贴个lsdsjy大牛的线段树的做法:http:// ...

  6. 解题:USACO14OPEN Fair Photography

    题面 有点像JRY的那道序列题,大概是统计题的经典套路? 先说无修改的:将白奶牛记为$-1$,花奶牛记为$1$,然后做前缀和统计某个前缀和$sum$第一次出现的位置,之后再出现就统计答案.对于修改(将 ...

  7. USACO 2014 US Open Fair Photography /// 技巧

    题目大意: 给定n头奶牛 给定n头奶头所在位置和品种 品种只有G H两种 求一段区间的长度 要求区间内包含的品种满足各品种的数量相同 将一个品种的值设为1 另一个设为-1 假设 i<j 而 1~ ...

  8. BZOJ-USACO被虐记

    bzoj上的usaco题目还是很好的(我被虐的很惨. 有必要总结整理一下. 1592: [Usaco2008 Feb]Making the Grade 路面修整 一开始没有想到离散化.然后离散化之后就 ...

  9. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

随机推荐

  1. Python-OpenCV中的resize()函数

    改变图像大小意味着改变尺寸,无论是单独的高或宽,还是两者.也可以按比例调整图像大小. 这里将介绍resize()函数的语法及实例. 语法 函数原型 cv2.resize(src, dsize[, ds ...

  2. PSNR

    PSNR,峰值信噪比,通常用来评价一幅图像压缩后和原图像相比质量的好坏,当然,压缩后图像一定会比原图像质量差的,所以就用这样一个评价指标来规定标准了.PSNR越高,压缩后失真越小.这里主要定义了两个值 ...

  3. Dojo的declare接口

    declare(classname,[],{}) declare的第一个参数是可选的,代表类的名称 declare的第二个参数代表类的继承关系,比如继承哪一个父类,可以看到:第二个参数是一个数组,所以 ...

  4. Bootstrap历练实例:可取消的警告

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  5. 【转】关于“using namespace std”

    对于一个存在着标准输入输出的C++控制台程序,一般会在#include <iostream>的下一行发现一句话,using namespace std.这句话其实就表示了所有的标准库函数都 ...

  6. poj3335 Rotating Scoreboard

    题目描述: vjudge POJ 题解: 半平面交判核的存在性. 重点在于一个点的核也算核. 这样的话普通的求多边形的版本就要加一个特判. 就是把剩下的一个节点暴力带回所有直线重判,这时判叉积是否$\ ...

  7. Python json和simplejson的使用

    在Python中,json数据和字符串的转换可以使用json模块或simplejson模块. json从Python2.6开始内置到了Python标准库中,我们不需要安装即可直接使用. simplej ...

  8. 运用Python制作你心目中的完美女神脸!

    简介 写这个项目的本来目的是通过构建一个神经网络来训练人脸图片,最后达到能根据图片自动判断美丑的效果.可能是因为数据集过小,或者自己参数一直没有调正确,无论我用人脸关键点训练还是卷积神经网络训练,最后 ...

  9. bs4--官文--搜索文档树

    搜索文档树 Beautiful Soup定义了很多搜索方法,这里着重介绍2个: find() 和 find_all() .其它方法的参数和用法类似,请读者举一反三. 再以“爱丽丝”文档作为例子: ht ...

  10. Linux学习-Tarball 的管理与建议

    使用原始码管理软件所需要的基础软件 从原始码的说明我们晓得要制作一个 binary program 需要很多咚咚的呢!这包括底下这些基础的软件: gcc 或 cc 等 C 语言编译程序 (compil ...