[JLOI2011]不重复数字

又是无聊写题解系列

题目传送门

刚学hash,个人觉得hash挺玄学的。

sol

题目意思清晰,\(t\)组数据,每一次给定n个数字,把只出现过一次的数字输出
刚看题,以为挺水的,暴力用逻辑数组存起来,\(O(n^2)\),可是数据范围为
\(1≤T≤50\)\(1≤n≤5×10^4\),一看就过不了嘛,所以我们要写hash表或者unordered_map。

关于unordered_map:

在C++11中,unordered_map作为一种关联容器,替代了hash_map,unordered_map的底层实现是\(hash\)表,所以被称为无序关联容器(源自baidu)

其实也很简单,也就是一种内部实现为\(hash\)表的\(STL\)容器,手写hash表呢就是先用前向星存起来,然后\(find\)函数一个for循环查找元素,也不会很难理解。
这道题是一道\(hash\)表模板题,比较基础。

code

解法①:\(hash表\)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
inline int rd(){
	int sign=1,res=0;char ch;
	while((ch=getchar())<'0'||ch>'9')if(ch=='-')sign=-1;res=res*10+ch-48;
	while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;
	return res*sign;
}
const int mod=200003;
ll cnt,n,m,t,h[200111],pre[200111];
ll nxt[200111],ans[200111];
void clear(){//清空数组 
	memset(pre,0,sizeof(pre));
	memset(h,0,sizeof(h));
	memset(nxt,0,sizeof(nxt));
}
void add(ll x){//前向星存图 
	int t=(x%mod+mod)%mod;//控制负数,这很重要 
	pre[++cnt]=x;
	nxt[cnt]=h[t];
	h[t]=cnt;
}
bool find(ll x){
	ll t=(x%mod+mod)%mod;//同上 
	for(ll i=h[t];i;i=nxt[i])
	  if(pre[i]==x)//如果找到了这个数 
	    return true;//就返回真 
	return false;//否则返回否 
}
int tot;
bool flag;
int main(){
	t=rd();
	while(t--){
		cnt=0,tot=0;
		clear();
		n=rd();
		for(ll i=1,x;i<=n;i++){
		   x=rd();//读入进来 
		   if(find(x))continue;//如果这个数出现过了,就进入下一次循坏 
		   ans[++tot]=x,add(x);//否则就存起来,标记一下,ans,数组用来存答案控制格式 
	    }
	    for(int i=1;i<=tot-1;i++)
	     printf("%d ",ans[i]);
	    printf("%d\n",ans[tot]);//完美输出 
	}
	return 0;
}

解法②:STL(unordered_map)

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int rd(){
	int res=0,sign=1;char ch;
	while((ch=getchar())<'0'||ch>'9')if(ch=='-')sign=-1;res=res*10+ch-48;
	while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;
	return res*sign;
}
int t,n;
unordered_map<int,bool> a;
int main(){
    t=rd();
    while(t--){
    	a.clear();//清空
    	n=rd();
    	for(int i=1,x;i<=n;i++){
    		x=rd();
    		if(!a[x]){//如果没有标记过,即第一次出现时
    			printf("%d ",x);
    			a[x]=1;//就标记起来
			}
		}
		cout<<endl;
	}
	return 0;
}

个人觉得STL还是好理解一点

完结撒花

posted @ 2020-05-22 21:52  qzwer  阅读(83)  评论(0编辑  收藏  举报