POJ 3274 Gold Balanced Lineup

本文介绍了一种算法问题——寻找给定特征集合中最大的平衡区间,并提供了两种解决方案:一种是通过排序实现,另一种是利用哈希表进行优化。文章详细解释了如何将问题转化为二进制表示,并通过示例说明了解决方案的具体步骤。

题意:FJ 有N头牛,N最多是10^5 ,每头牛最多有30种特征,一头牛所具有的特征可以用一个数来表示,将这个数化成2进制,第i位上权为1,说明它具有第i种特征,如果有一个区间(牛编号连续),使得这个区间的牛的每种特征之和相等,则这个区间为平衡区间。现在告诉你牛的个数n,特征个数k和每头牛的特征值,让你求最大的平衡区间。

分析转自:here:

这个题目的转化有点困难,看了别人的报告才明白是怎么回事。
给出SAMPLE
7 3
7
6
7
2
1
4
2
先转化成二进制:
1 1 1
1 1 0
1 1 1
0 1 0
0 0 1
1 0 0
0 1 0
然后在列上进行累加:
1 1 1
2 2 1<----
3 3 2
3 4 2
3 4 3
4 4 3<----
4 5 3
上面这两步转化还好想。答案是4,是因为两个箭头所指的行列上的差相等。
然后在行上,所有值减去最右边的数:
0 0 0
1 1 0<----
1 1 0
1 2 0
0 1 0
1 1 0<----
1 2 0
这一步转化推一下就知道,不过实在不好想。
然后找出两个一样的行,使他们的距离最远。答案就是最远的距离。

Code(方法一):

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define eps 1e-7
#define LL long long
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;

const int maxn=100005;
int k;
struct node{
    int d[33],id;
    bool operator <(const node &a)const {
        for(int i=k-1;i>=0;i--) if(d[i]!=a.d[i])
            return d[i]<a.d[i];
        return id<a.id;
    }
    bool operator == (const node &a)const {
        for(int i=k-1;i>=0;i--) if(d[i]!=a.d[i])
            return false;
        return true;
    }
}List[maxn];

int main()
{
    int n,x;
    scanf("%d %d",&n,&k);
    if(n==1){
        printf("1\n");
        return 0;
    }
    memset(List,0,sizeof(List));
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        List[i].id=i;
        for(int j=0;j<k;j++){
            List[i].d[j]=(x&1)+List[i-1].d[j];
            x>>=1;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<k;j++)
            List[i].d[j]-=List[i].d[0];
        List[i].d[0]=0;
    }
    sort(List,List+1+n);
    List[n+1].d[0]=-0x3f3f3f3f;
    int i=0,j=0,ans=0;
    while(i<=n){
        while(List[i]==List[j]) j++;
        ans=Max(ans,List[j-1].id-List[i].id);
        i=j;
    }
    printf("%d\n",ans);
    return 0;
}

Code(方法二hash):

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#define eps 1e-7
#define LL long long
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;

const int maxn=100005;
const int HASH=100003;
int n,k;
int bit[maxn][33],head[HASH],Next[HASH];

int get_hash(int v[]){
    int h=0;
    for(int i=0;i<k;i++) h=(h<<2)+(v[i]>>4)^(v[i]<<10);
    h%=HASH;
    h=h<0?h+HASH:h;
    return h;
}
bool issame(int x[],int y[]){
    for(int i=0;i<k;i++) if(x[i]!=y[i])
        return false;
    return true;
}

int main()
{
    scanf("%d %d",&n,&k);
    memset(bit[0],0,sizeof(bit[0]));
    memset(head,-1,sizeof(head));
    int x,ans=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        for(int j=0;j<k;j++) {
            bit[i][j]=bit[i-1][j]+(x&1);
            x>>=1;
        }
    }
    for(int i=0;i<=n;i++){
        for(int j=1;j<k;j++) bit[i][j]-=bit[i][0];
        bit[i][0]=0;
        int tmp=get_hash(bit[i]);
        for(int id=head[tmp];id!=-1;id=Next[id]){
            if(issame(bit[i],bit[id])){
                ans=Max(ans,i-id);
            }
        }
        Next[i]=head[tmp];
        head[tmp]=i;
    }
    printf("%d\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值