原题:POJ3274

参考:进击的阿俊


已知有n头牛,用一个K位二进制数Ak,Ak-1,...,A1表示一头牛具有的特征,Ai=1表示具有特征i。现给定按顺序排列的N头牛的k位特征值,称某个连续范围内“特征平衡”,假如在这个范围内,拥有各个特征的牛的数量都相等。求最大“特征平衡”连续范围。

分析:

用sum[i][j]( 1<=i<=n, 1<=k<=j)表示1到第i头牛中具有特征j的牛的数量。问题转化为求解满足sum[i][l] - sum[j][l] = sum[i][1] - sum[j][1](l = 1,2,..,k)的最大i - j的值。很容易想到最简单的方法,通过令d = n to 1,判断是否存在i,使得sum[i + d][j] - sum[i][j] = sum[i + d][1] - sum[i][j],时间复杂度为O(n*n*k)。由于n的最大值能达到100000,必须选择一个更加优化的方法。

1)容易验证,sum[i][l] - sum[j][l] = sum[i][1] - sum[j][1] ( l = 1,2,..,k ) 等价于sum[i][l] - sum[i][1] = sum[j][l] - sum[j][1] ( l = 1,2,...k )。因此令d[i][j] =  sum[i][j] - sum[i][1] ,问题就转化为求解使得d[i][j] = d[i + size][j]的最大size。

2)为进一步简化算法,对于任意 1<= i <=n, 令sig[i] = (d[i][1] + d[i][2] + ... +d[i][k] ) % m (m为一个较大的质数)。这样,若对于i和j, sig[i] != sig[j],那么必定不会满足d[i][] = d[j][],就无需再对它进行验证;若满足sig[i] = sig[j],才需要进一步确定是否有d[i][] = d[j][]。

3)用h[k] (1 <= k <= m,m为以上取模运算的素数)记录满足sig[i] = k的i值。通过令 i = 1 to n,以此更新h[sig[i]]和largest,即可得到结果。


样例输入

7 3
7
6
7
2
1
4
2

样例输出

4


//
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath> using namespace std; const int maxn = 100010;
const int maxk = 31;
int n, k, tmp;
bool cow[maxn][maxk];
int sum[maxn][maxk];
int d[maxn][maxk]; //d 和 sig辅助计算哈希值
int s, size;
const int prime = 49117;
int sig[maxn];
int largest; vector <int> h[prime]; //哈希表 void search(int i, int t)//0 1 \ 2 2 \ 2 3 \ 3 4 \
{
int size = h[i].size();
for (int j = 0; j < size; j++) {
bool flag = 1;
for (int l = 0; l < k; l++) {
//printf("d[h[%d][%d]:%d][%d]:%d ==? d[%d][%d]:%d\n",i,j,h[i][j],l,d[h[i][j]][l],t,l,d[t][l]);
if ( d[ h[i][j] ][l] != d[t][l] ) {
flag = 0;
break;
}
}
if (flag) {
if (t - h[i][j] > largest)
largest = t - h[i][j];
return;
}
}
h[i].push_back(t);
//printf("i:%d push back t:%d\n",i,t);
} int findLargest()
{
largest = 0;
for (int i = 1; i <= n; i++) {
search(sig[i], i);
printf("%d\n",largest);
}
return largest;
} void init()
{
memset(sum, 0, sizeof(sum));
memset(sig, 0, sizeof(sig));
for (int i = 0; i < prime; i++) h[i].clear();
h[0].push_back(0);
for (i = 1; i <= n; i++) {
for (int j = 0; j < k; j++) {
sum[i][j] = sum[i - 1][j] + cow[i][j];
d[i][j] = sum[i][j] - sum[i][0];
sig[i] += d[i][j];
//printf("%d ",d[i][j]);
//printf("%d ",d[i][j]);
}
//printf("%d\n",sig[i]);
/*
for (j = 0; j < k; j++) {
sig[i] += d[i][j];
}
*/
sig[i] = abs(sig[i]) % prime;
}
} int main()
{
//while (1) {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++ ) {
scanf("%d", &tmp);
for (int j = 0; j < k; j++) {
cow[i][j] = tmp % 2;
tmp /= 2;
}
}
init();
findLargest();
printf("%d\n", largest);
//}
return 0;
}

POJ3274-牛的属性-HASH-ACM的更多相关文章

  1. 牛客网暑期ACM多校训练营(第四场):A Ternary String(欧拉降幂)

    链接:牛客网暑期ACM多校训练营(第四场):A Ternary String 题意:给出一段数列 s,只包含 0.1.2 三种数.每秒在每个 2 后面会插入一个 1 ,每个 1 后面会插入一个 0,之 ...

  2. 牛客网暑期ACM多校训练营(第五场):F - take

    链接:牛客网暑期ACM多校训练营(第五场):F - take 题意: Kanade有n个盒子,第i个盒子有p [i]概率有一个d [i]大小的钻石. 起初,Kanade有一颗0号钻石.她将从第1到第n ...

  3. 牛客网 暑期ACM多校训练营(第二场)A.run-动态规划 or 递推?

    牛客网暑期ACM多校训练营(第二场) 水博客. A.run 题意就是一个人一秒可以走1步或者跑K步,不能连续跑2秒,他从0开始移动,移动到[L,R]的某一点就可以结束.问一共有多少种移动的方式. 个人 ...

  4. 牛客网 暑期ACM多校训练营(第一场)A.Monotonic Matrix-矩阵转化为格子路径的非降路径计数,Lindström-Gessel-Viennot引理-组合数学

    牛客网暑期ACM多校训练营(第一场) A.Monotonic Matrix 这个题就是给你一个n*m的矩阵,往里面填{0,1,2}这三种数,要求是Ai,j⩽Ai+1,j,Ai,j⩽Ai,j+1 ,问你 ...

  5. 牛客网暑期ACM多校训练营(第三场)H Diff-prime Pairs (贡献)

    牛客网暑期ACM多校训练营(第三场)H Diff-prime Pairs (贡献) 链接:https://ac.nowcoder.com/acm/contest/141/H来源:牛客网 Eddy ha ...

  6. 2018牛客网暑期ACM多校训练营(第二场)I- car ( 思维)

    2018牛客网暑期ACM多校训练营(第二场)I- car 链接:https://ac.nowcoder.com/acm/contest/140/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 ...

  7. 牛客网暑期ACM多校训练营(第七场)Bit Compression

    链接:https://www.nowcoder.com/acm/contest/145/C 来源:牛客网 题目描述 A binary string s of length N = 2n is give ...

  8. 2018牛客网暑假ACM多校训练赛(第五场)H subseq 树状数组

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round5-H.html 题目传送门 - https://www.no ...

  9. 2018牛客网暑假ACM多校训练赛(第四场)E Skyline 线段树 扫描线

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round4-E.html 题目传送门 - https://www.no ...

  10. poj3274 Gold Balanced Lineup(HASH)

    Description Farmer John's N cows (1 ≤ N ≤ 100,000) share many similarities. In fact, FJ has been abl ...

随机推荐

  1. JavaScript高级程序设计14.pdf

    继承,ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 构造函数.原型.和实例的关系:每个构造函数都有一个原型对象,每个原型对象都包含一个指向构造函数的指针,每个实例都包含一 ...

  2. spring maven pom

    https://spring.io/blog/2009/12/02/obtaining-spring-3-artifacts-with-maven/

  3. poj 2449 第k短路

    题目链接:http://poj.org/problem?id=2449 #include<cstdio> #include<cstring> #include<iostr ...

  4. Java 23种设计模式详尽分析与实例解析之一--创建型模式

    面向对象的设计原则 常用的面向对象设计原则包括7个,这些原则并不是独立存在的,它们相互依赖.互为补充. Java设计模式 创建型模式 简单工厂模式 模式动机: 考虑一个简单的软件应用场景,一个软件系统 ...

  5. c# 发送邮件、附件 分类: C# 2014-12-17 16:41 201人阅读 评论(0) 收藏

    WinForm窗体代码如下: <span style="font-size:14px;">using System; using System.Collections. ...

  6. 【设计模式 - 1】之工厂模式(Factory)

    1      模式简介 1.1    工厂模式作用 工厂模式解决的是"使用new关键字获取对象造成松耦合"的问题. 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏 ...

  7. 【设计模式 - 19】之观察者模式(Observer)

    1      模式简介 观察者模式的介绍: 观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新. 发布者(被观察者) + 订阅者(观察者) ...

  8. 关于session的实现:cookie与url重写

    本文讨论的语境是java EE servlet. 我们都知道session的实现主要两种方式:cookie与url重写,而cookie是首选(默认)的方式,因为各种现代浏览器都默认开通cookie功能 ...

  9. FreeMarker 自己定义指令(三)

    1. 模板文件 test04.ftl foo <@customUpper> bar f <#-- 这里同意使用全部的 FTL --> <#list ["red& ...

  10. oracle中 sql%rowcount 使用方法

    sql%rowcount用于记录改动的条数,必须放在一个更新或者删除等改动类语句后面运行,select语句用于查询的话无法使用, 当你运行多条改动语句时,依照sql%rowcount 之前运行的最后一 ...