[JLOI2011]不重复数字 题解

前言

本题是一道哈希表的模板题。然而当时的 data maker 竟然连直接开桶的做法都没有卡掉...
于是在 Luogu 上,很长一段时间之内,这道题的最优解一直是这个错解。
而且,虽然题面上写着给出的数在 32 位有符号整数范围内,但是 data maker 也没有出出来负数...导致一些错误的哈希表做法也 AC 了(比如说我之前的哈希表代码)。
然后今天凌晨偶然看到了这道题目,重新写了一遍之后,提交到 Luogu 上面去,发现炸成了 60 分!
看了一眼之前的提交记录:怎么哈希表做法都炸成 60 分了?只有几个 map 在那里苟延残喘。
然后提交到了 BZOJ 上,发现 AC 啦!于是一度以为 Luogu 数据错了!然而发现评论区一车人说 60 分的,于是又翻了一会帖子,发现管理员改了数据!
QAQ...于是改了一会,发现这个哈希函数在接收负数时会出现负数的数组下标!然而自己负数取模都写错了 2 遍。
当然,最后还是 AC 啦,故作文以记之。

正文

水题。每次读入一个数,就尝试插入哈希表。如果已经在哈希表中出现了,即取消插入。否则,插入后直接输出该数即可。
需要注意的是,此题数据范围极大,所以需要使用较快的读入方式。
Code:

#include <bits/stdc++.h>
using namespace std;
const int P=50021;
#define int long long
struct node {int v,nxt;}rec[10+P];
int hd[10+P],n;
namespace HASH {
int tot;
int H(int x) {return (x%P+P)%P;}
bool add(int x, int v) {
    for (int i=hd[x];i;i=rec[i].nxt) if (rec[i].v==v) return false;
    rec[++tot].v=v;
    rec[tot].nxt=hd[x];
    hd[x]=tot;
    return true;
}
}
using HASH::tot;
using HASH::H;
using HASH::add;
void rd(int&),wt(int);
#undef int
int main() {
#define int long long
    int T;rd(T);
    while(T--) {
        tot=0;memset(rec,0,sizeof rec);memset(hd,0,sizeof hd);rd(n);
        while (n--) {
            int x;rd(x);
            if (add(H(x),x)) wt(x),putchar(' ');
        }
        puts("");
    }
    return 0;
}
void rd(int& x) {
    x=0;int f=1;char ch=getchar();
    while (!isdigit(ch)) (ch=='-')&&(f=-1),ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x*=f;
}
void wt(int x) {
    (x<0)&&(x=-x,putchar('-'));
    if (x>9) wt(x/10);putchar(x%10^48);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章