poj3274~改吐了的哈希表

本文介绍了一种求解区间内平衡数的最大间隔的算法。通过位运算统计区间内每位数的个数,并利用哈希表存储这些统计数据,进而找出最长的平衡区间。平衡区间定义为区间内每位数的个数相同。

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

改了一晚上才改对,疯了,没法说更多了

/* sum[i][j]代表0到i这个区间内 ,每位数的个数,j代表是第几位。
明显sum[a][j]-sum[b][j]中每个j都是相等时说明这个区间内是“平衡”的
所以可以用c[i][j]代表是否2者区间内是否平衡,c[i][j]=sum[i][j]-sum[i][0];
*/
#include<iostream>
#include<string>
#include<cmath>
#define M 100005
using namespace std;

int n,k,Max,flag,sum[M][32],c[M][32],vis[M];
struct COW
{
	int v;
	int p;
	struct COW *next;
};
struct COW *hash[M];

void insert(struct COW *h,int i)
{
	int m;
	if(h->v==0)
	{
		h->v=1;
		h->p=i;
		h->next=new struct COW;
		h->next->v=0;
	}
	else
	{
		int f=1;
		for(int j=0;j<k;j++)  //判断这个hash中是否有平衡区间,即二者的c全部相等的
			if(c[i][j]!=c[h->p][j])
			{
				f=0;
				break;
			}
			
		m=i-(h->p); //这个就是距离
		if(f&&m>Max)
		{
	
			Max=m;
		}
		insert(h->next,i);
	}
} 

int main()
{
	int i,j,x,m,key;

	memset(vis,0,sizeof(vis));
	scanf("%d%d",&n,&k);

	for(j=0;j<k;j++)    //给0初始化,i是从1开始的
	{
		sum[0][j]=0;
		c[0][j]=0;
	}
	vis[0]=1;  //往hash中插入0
	hash[0]=new struct COW;
	hash[0]->v=0;
	hash[0]->next=NULL;
	insert(hash[0],0);

	Max=flag=0;
	
	
	for(i=1;i<=n;i++)
	{
		scanf("%d",&x);
		for(j=0;j<k;j++)
		{
			sum[i][j]=(x&1)+sum[i-1][j];  //位运算用在与二进制有关的题目真的非常好用!
			/* 注意,x&1+1 =x&(1+1)*/
			x=x>>1;
		}
		
		key=0;
		for(m=0;m<k;m++)
		{
			c[i][m]=sum[i][m]-sum[i][0];  //算c
			key+=c[i][m]*m; //hash的key值为c值*m的总和
		}
	
		key=abs(key);
		key=key%M;
	
		if(vis[key]==0)
		{
			vis[key]=1;
			hash[key]=new struct COW;
			hash[key]->v=0;
			hash[key]->next=NULL;
		}
	
		insert(hash[key],i);
	
	}
	printf("%d\n",Max);
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值