0
点赞
收藏
分享

微信扫一扫

A-B数对——题目解析

jjt二向箔 2022-04-21 阅读 55

题目来源: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吗……)

举报

相关推荐

P1102 A-B 数对

A-B数对 多种方法 洛谷p1102

【字符匹配消除】A-B

L1-011 A-B

L1-011 A-B (20 分)

简单A-B(二分,map,双指针)

PAT--L1-011 A-B (C语言)

0 条评论