poj 3274 Gold Balanced Lineup, 拉链式hash

sum[i][j] 表示从第1到第i头cow属性j的出现次数

所以题目要求等价为:

求满足

sum[i][0]-sum[j][0]=sum[i][1]-sum[j][1]=.....=sum[i][k-1]-sum[j][k-1] (j<i)

中最大的i-j

将上式变换可得到

sum[i][1]-sum[i][0] = sum[j][1]-sum[j][0]

sum[i][2]-sum[i][0] = sum[j][2]-sum[j][0]

......

sum[i][k-1]-sum[i][0] = sum[j][k-1]-sum[j][0]

令C[i][y]=sum[i][y]-sum[i][0] (0<y<k)

初始条件C[0][0~k-1]=0

所以只需求满足C[i][]==C[j][] 中最大的i-j,其中0<=j<i<=n。

C[i][]==C[j][] 即二维数组C[][]第i行与第j行对应列的值相等,

那么原题就转化为求C数组中 相等且相隔最远的两行的距离i-j。

将C[i]进行hash,

这样就可以高效的找到i前面C[i]=C[j]的所有j了。

采用拉链式hash表能有效的避免冲突

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 100000 + 5;
const int maxk = 30 + 5;
const int mod = 99983;
int sum[maxn][maxk], c[maxn][maxk];
int head[maxn], next[maxn], v[maxn], ecnt;
int n, k;

void addedge(int a, int b) {
    next[ecnt] = head[a];
    head[a] = ecnt;
    v[ecnt] = b;
    ecnt++;
}
// BKDR Hash Function
int hash(int *v) {
    unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
    unsigned int hash = 0;
    for(int i=0; i<k; ++i)
        hash = hash * seed + v[i];
    return (hash & 0x7FFFFFFF) % mod;
}

int main() {
    memset(sum, 0, sizeof sum );
    memset(c, 0, sizeof c );
    memset(head, -1, sizeof head );
    ecnt = 0;
    int ans = 0;
    addedge(hash(c[0]), 0);

    scanf("%d%d", &n, &k);
    for(int i=1; i<=n; ++i)
    {
        int a;
        scanf("%d", &a);
        for(int j=0; j<k; ++j)
        {
            sum[i][j] = sum[i-1][j] + (1&a);
            c[i][j] = sum[i][j] - sum[i][0];
            a >>= 1;
        }

        int h = hash(c[i]);
        for(int j=head[h]; j != -1; j=next[j])
        {
            bool flag = true;
            for(int p=0; p<k; ++p)
            if(c[v[j]][p] != c[i][p])
            {
                flag = false;
                break;
            }
            if(flag && ans < i-v[j])
                ans = i - v[j];
        }
        addedge(h, i);
    }
    printf("%d\n", ans);
    return 0;
}

/*
7 3
7
6
7
2
1
4
2

ans:
4
*/

poj 3274 Gold Balanced Lineup, 拉链式hash

时间: 2024-08-25 13:23:39

poj 3274 Gold Balanced Lineup, 拉链式hash的相关文章

poj 3274 -- Gold Balanced Lineup

Gold Balanced Lineup Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12110   Accepted: 3553 Description Farmer John's N cows (1 ≤ N ≤ 100,000) share many similarities. In fact, FJ has been able to narrow down the list of features shared

POJ 3474 Gold Balanced Lineup Hash

题意一开始不是很明确, 后来发现是每一种特征出现的次数相同 这样一来就变成简单hash问题了,如果把每个特征看看做是一个(n+1)进制数的话,对奶牛序列求一下前缀和,如果i - j这一段每一种特征出现的次数相同的话,把i - 1点和j点的每一位减去所有位中的最小值之后,必然相等,所以hash判断一下就好. #include <cstdio> #include <cstring> #include <iostream> #include <map> #incl

poj3274(Gold Balanced Lineup)

题目地址:Gold Balanced Lineup 题目大意: 一个农场有N个奶牛,每个奶牛都有不同的特征,聪明的农夫给奶牛 feature ID.代表奶牛所具有的特征.将feature ID 写成为K位的二进制的数,其中有1的位置代表奶牛具有此特征,0代表没有此特征.从i->j 使这个区间的奶牛所有特征的个数是相等的.其中最大的区间差就是题图所求的. 解题思路: 解题思路: 经典题,不转化问题很难做,先根据官方的方法转化问题,把“求最远的两行间各个特征出现次数相等”转化为“求最远的相同两行”,

bzoj1702[Usaco2007 Mar]Gold Balanced Lineup 平衡的队列*

bzoj1702[Usaco2007 Mar]Gold Balanced Lineup 平衡的队列 题意: N头牛,一共K种特色.每头牛有多种特色.[i,j]段被称为balanced当且仅当K种特色在[i,j]内拥有次数相同.求最大的[i,j]段长度.n≤100000,k≤30. 题解: 得到式子:a[i][l]-a[j][l]=a[i][l-1]-a[j][l-1],l在2..k之间,移项得a[i][l]-a[i][l-1]=a[j][l]-a[j][l-1],l在2..k之间,故可以定义一个

1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列

1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 510  Solved: 196[Submit][Status][Discuss] Description Farmer John's N cows (1 <= N <= 100,000) share many similarities. In fact, FJ has been able to narrow

【POJ】3264 Balanced Lineup ——线段树 区间最值

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 34140   Accepted: 16044 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

POJ 3264:Balanced Lineup Rmq模板

Balanced Lineup 题目链接: http://poj.org/problem?id=3264 题意: 求区间最大值和最小值的差 题解: Rmq模板题 代码 #include<stdio.h> #include<math.h> const int N=5e4+1; int dpmax[N][17]; int dpmin[N][17]; int mmax(int x,int y) { return x>y?x:y; } int mmin(int x,int y) {

POJ 题目3264 Balanced Lineup(RMQ)

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 39046   Accepted: 18291 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

Gold Balanced Lineup - poj 3274 (hash)

这题,看到别人的解题报告做出来的,分析: 大概意思就是: 数组sum[i][j]表示从第1到第i头cow属性j的出现次数. 所以题目要求等价为: 求满足 sum[i][0]-sum[j][0]=sum[i][1]-sum[j][1]=.....=sum[i][k-1]-sum[j][k-1] (j<i) 中最大的i-j 将上式变换可得到 sum[i][1]-sum[i][0] = sum[j][1]-sum[j][0] sum[i][2]-sum[i][0] = sum[j][2]-sum[j]