BZOJ2761 / JLOI2011 不重复的数【平衡树?哈希!】

来源:互联网 发布:空间网络音乐怎么删除 编辑:程序博客网 时间:2024/05/17 07:30

Description

给出N个数,要求把其中重复的去掉,只保留第一次出现的数。
例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 6 5 4。

Input

输入第一行为正整数T,表示有T组数据。
接下来每组数据包括两行,第一行为正整数N,表示有N个数。第二行为要去重的N个正整数。

Output

对于每组数据,输出一行,为去重后剩下的数字,数字之间用一个空格隔开。

Solution

我为什么要写平衡树?这题瞎搞不是挺好的吗

该题解法是瞎搞的伪哈希暴力!平衡树什么的去死吧!
关键在于判重。
于是我筛了5个1e6的质数,每个x去取模标记vis[0..4](至于负数嘛就什么对巨大数取模再加个巨大数什么的)。判的时候判vis[0..4][对质数取模]是不是都访问过了,不是就判为没有啦!
然后如果5个vis都访问了,可能是巧合,于是暴力搜一遍。
然后过了……

代码:

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1000000;const int M = 5;const int b = 19260817;int hash[M] = {999953, 999959, 999961, 999979, 999983};bool vis[M][maxn];int n, A[maxn], cnt;void init(){    memset(vis, 0, sizeof vis);    memset(A, 0, sizeof A);    n = cnt = 0;}bool exs(int x, int r){    for (int i = 0; i < M; i++)        if (!vis[i][x % hash[i]]) return 0;    for (int i = 1; i <= cnt; i++)        if (A[i] == r) return 1;    return 0;}void Insert(int x, int r){    for (int i = 0; i < M; i++)        vis[i][x % hash[i]] = 1;    A[++cnt] = r;}int main(){    int t; scanf("%d", &t);    while (t--){        init();        scanf("%d", &n);        for (int i = 1; i <= n; i++){            int r; scanf("%d", &r);            int x = r > 0 ? r : (r % b + b * 2);            if (exs(x, r)) continue;            else{                Insert(x, r);                if (i == 1) printf("%d", r);                else printf(" %d", r);            }        }        puts("");    }    return 0;}
原创粉丝点击