A-B数对——题目解析

题目来源:Luogu P1102,OJ 1522
在这里插入图片描述

解法1:Hash表(取模hash函数+开散列表-拉链法)

#include<iostream>
using namespace std;
const int N = 200005;
const int P = 1000003;
int n,c,x,tot = 0;
long long ans = 0;//1e10要开long long了 
struct Node{
	int data;
	int cnt;
	int next;
	Node(){
		data = 0;
		cnt = 0;
		next = 0;
	}
}node[N];
int head[P] = {0};

void _insert(int x){
	int p = head[x%P];
	if(p==0){
		head[x%P] = ++tot;
		node[tot].data = x;
		node[tot].cnt ++;
		return ;
	}
	while(p!=0){
		if(node[p].data == x) break;
		if(node[p].next)
			p = node[p].next ;
		else break;
	}
	if(node[p].data == x){
		node[p].cnt ++;
	}
	else{
		node[p].next = ++tot;
		node[tot].data = x;
		node[tot].cnt ++;
	}
}

long long find(int k){
	int p = head[k%P];
	if(p==0) return 0;
	while(p!=0){
		if(node[p].data == k) break;
		if(node[p].next == 0) break;
		p = node[p].next ; 
	}
	if(node[p].data == k) return node[p].cnt ;
	return 0;
} 

long long _solve(int k){
	long long cnt1 = find(node[k].data);
	long long cnt2 = find(node[k].data+c);
	return cnt1*cnt2;
}

int main(){
	cin>>n>>c;
	for(int i=1;i<=n;i++){
		cin>>x;
		_insert(x);
	}
//	for(int i=1;i<=10;i++){
//		cout<<"head["<<i<<"]"<<head[i]<<endl;
//	}
//	for(int i=1;i<=tot;i++){
//		cout<<"node["<<i<<"] "<<"data "<<node[i].data<<"cnt "<<node[i].cnt<<endl;
//	}
	for(int i=1;i<=tot;i++){
		ans += _solve(i);
	}
	cout<<ans<<endl;
	return 0;
}

有一些没有搞懂的问题是,an是绝对值小于等于230,那么可能是负数。对负数直接取模,得到的结果还是负数,为什么这里head数组使用的时候并没有CE?(按理说,如果下标为负,应该是会变成非法访问?)那么为了解决负数取模的问题,是否要用abs取绝对值?

解法2:看到有sort(nlogn)+双指针(即可以配对的那一段数组头尾指针相减算长度,复杂度介于nlogn和n2之间?肯定是到不了n2,但是具体多少我也不知道捏)的做法

解法3:可以sort+二分(标准的logn)

解法4:map(………………不是不让用STL吗……)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值