HDU5199

题目链接:点击打开链接

题目大意就是统计每一个数字出现过多少次,数字范围在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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值