题目链接:点击打开链接
题目大意就是统计每一个数字出现过多少次,数字范围在10^9内,数据范围为10^6。
首先想到的是哈希,但是简单哈希感觉容易被cha,对数模上一个大素数,比如100007(10^5),这样很容易构造一组数据,比如100007*k(k为整数),满足这个条件且在10^9之内的数字大约有10^4个,这样碰撞的就太多了,总查询复杂度会飚到10^10,所以想了一个稍微复杂的哈希,每个数字乘上它的数位再模上一个大素数,为了防爆就用了long long。结果t了n多发.....
补充了姿势以后才知道,原来系统对long long的速度比起int是奇慢无比的,某贴吧截图
数据比较水,所以直接取模就过了。
(用了输入挂比没用输入挂还慢了几十毫秒..不懂)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define N 1000010
using namespace std;
#define Mod 100009
int h[N],q[N];
typedef struct node{
int val;
int cnt;
};
vector<node>Hash[Mod];
void Insert(int a){
int k;
k = a;
k %= Mod;
bool flag = true;
node tmp;
for(int i = 0;i < Hash[k].size() ;i++){
if(Hash[k][i].val == a){
Hash[k][i].cnt++;
flag = false;
break;
}
}
if(flag) {
tmp.cnt = 1;
tmp.val = a;
Hash[k].push_back(tmp);
}
}
int query(int a){
int ret = 0;
int k;
k = a;
k %= Mod;
for(int i = 0;i < Hash[k].size(); i++){
if(Hash[k][i].val == a){
ret = Hash[k][i].cnt;
Hash[k][i].cnt = 0;
break;
}
}
return ret;
}
int main(){
int n,m,ans;
while(~scanf("%d%d",&n,&m)){
int t;
for(int i =0; i < n;i++) {
scanf("%d",&t);
Insert(t);
}
for(int i =0;i < m;i++) {
scanf("%d",&t);
ans = query(t);
printf("%d\n",ans);
}
for(int i = 0;i < Mod; i++) Hash[i].clear();
}
return 0;
}
看了官方题解还有一种方法,就是先排序,然后统计所有相同的数字计数,查询的时候二分查询即可。
另外直接用map也可以解决
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <map>
#define N 1000010
using namespace std;
int h[N],q[N];
map<int,int> Map;
int main(){
int n,m,ans;
while(~scanf("%d%d",&n,&m)){
int t;
for(int i =0; i < n;i++) {
scanf("%d",&t);
map<int,int>::iterator p;
p = Map.find(t);
if(p!=Map.end()) (p->second)++;
else Map.insert(pair<int,int>(t,1));
}
for(int i =0;i < m;i++) {
scanf("%d",&t);
map<int,int>::iterator p;
p = Map.find(t);
if(p!=Map.end()) {
ans = p->second;
p->second = 0;
}
else ans = 0;
printf("%d\n",ans);
}
Map.clear();
}
return 0;
}