Gold Balanced Lineup POJ - 3274 Hash表应用

本文介绍了一种算法,用于解决寻找具有相等二进制位计数的最大子数组长度的问题。通过将输入转化为二进制形式并利用哈希表进行优化,实现了高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先说题意把,从网上找到了一个能很好解释题意的图片


下面我以此题举个例子

此题的输入如下

7 3 

7

6

7

2

1

4

2


也就是说有7头牛

将下面输入的7个数字每个数字都可以先转化内位数不超过3位的二进制数(注意顺序是从右向左)

先来转一下

           1   2    3          序号


7        1    1    1         1

6        0    1    1         2

7        1    1    1         3

2        0    1    0         4

1        1    0    0         5

4        0    0    1         6

2        0    1    0         7


举个例子来说明要求什么,从序号3到序号6之间

对应1的共有两个,对应2的共有两个,对应3的共有两个

也就是说此时的距离为6-3+1=4


我们要求的是最长的距离




           1   2    3          序号


7        1    1    1         1

6        1    2    2         2

7        2    3    3         3

2        2    4    3         4

1        3    4    3         5

4        3    4    4         6

2        3    5    4         7


上面图的意思是

设立一个数组sum[i][j]

i代表行数,j代表列数

sum代表从第一行的j列到第i行的j列中,j列共包含多少个1

我们发现当sum[j][1]-sum[i][1]=sum[j][2]-sum[i][2]=sum[j][3]=sum[i][3]的时候

存在一个(j-i+1)的区域长度符合条件。


我们把等式转换一下

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

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

下面是示例图(减去第一列)


           1   2    3          序号


7        0    0    0         1

6        0    1    1         2

7        0    1    1         3

2        0    2    1         4

1        0    1    0         5

4        0    1    1         6

2        0    2    1         7



基本上讲解到这里题意已经很清楚了,接下来用哈希表将sum[i][]和sum[j][]相同的存在一个哈希函数里

比如3和6对应一个哈希函数,存到对应哈希函数的vector里


最后我们查找哈希函数里区间最大的值作答案。




下面是代码实现


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;
#define prime 501
int c[100001][35],sum[100001][35];
int n,k;
int Max=0;
vector<int>ha[505];

bool cmp(int x,int y)
{
    for(int i=1; i<=k; ++i)
    {
        if(c[x][i]!=c[y][i])
            return false;
    }
    return true;
}


int main()
{
    int l;
    long long x;
    cin>>n>>k;
    for(int i=1; i<=n; ++i)
    {
        scanf("%lld",&x);
        for(int j=1; j<=k; ++j)
        {
            l=x%2;
            x=x/2;
            sum[i][j]=sum[i-1][j]+l;
        }
    }

    for(int i=1; i<=n; ++i)
    {
        int su=0;
        int tot=0;
        for(int j=1; j<=k; ++j)
        {
            c[i][j]=sum[i][j]-sum[i][1];
            if(!c[i][j])tot++;
            su=(su+c[i][j])%prime;
        }
        su=abs(su);
        if(tot==k && i>Max)Max=i;
        ha[su].push_back(i);
    }

    for(int i=0; i<prime; ++i)
    {
        int len=ha[i].size();
        if(len>1)
        {
            for(int j=0; j<len-1; ++j)
                for(int m=j+1; m<len; ++m)
                {
                    int l=ha[i][m]-ha[i][j];
                    if(l>Max&&cmp(ha[i][j],ha[i][m]))
                    {
                        Max=l;
                    }
                }
        }
    }
    cout<<Max<<endl;
}













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值