总览:
用来快速查询一个数/值/状态…
其实我也不是很了解
T1 P1102 A-B 数对
P1102 A-B 数对
题目描述
出题是一件痛苦的事情!
题目看多了也有审美疲劳,于是我舍弃了大家所熟悉的
A
+
B
P
r
o
b
l
e
m
A+B Problem
A+BProblem,改用
A
−
B
A-B
A−B 了哈哈!
好吧,题目是这样的:给出一串数以及一个数字
C
C
C,要求计算出所有
A
−
B
=
C
A-B=C
A−B=C 的数对的个数。(不同位置的数字一样的数对算不同的数对)
输入格式
第一行包括
2
2
2个非负整数
N
N
N和
C
C
C,中间用空格隔开。
第二行有 N N N个整数,中间用空格隔开,作为要求处理的那串数。
输出格式
输出一行,表示该串数中包含的所有满足
A
−
B
=
C
A−B=C
A−B=C的数对的个数。
输入输出样例
输入
4 1
1 1 2 3
输出
3
说明/提示
对于73%的数据,
N
≤
2000
N
≤
2000
N \le 2000N≤2000
N≤2000N≤2000;
对于100%的数据,
N
≤
200000
N
≤
200000
N \le 200000N≤200000
N≤200000N≤200000。
所有输入数据都在
l
o
n
g
i
n
t
longint
longint范围内。
思路:
A
−
B
=
C
即
B
+
C
=
A
A-B=C即B+C=A
A−B=C即B+C=A
统计每个数出现的个数,再查询累加。
注意:这道题是我做的第一道
h
a
s
h
t
a
b
l
e
hash table
hashtable的题,但是它tm 卡
h
a
s
h
hash
hash
解决方法…看代码!
代码:
#include<bits/stdc++.h>
using namespace std;
#define in Read()
long long in{
long long s=0,f=1;char x;
for(x=getchar();!isdigit(x);x=getchar()) if(x=='-') f=-1;
for( ;isdigit(x);x=getchar()) s=(s<<1)+(s<<3)+(x&15);
return s*f;
}
const int A=4e6+5;
const int mod=1e6+19;
const int add=23;
int n,c;
struct hash{
int num,x;
}h[A];
int s[A];
long long ans;
inline int hash(int x){
return abs(x%mod+add);
}
inline void putin(int a){
int x=hash(a);
while(h[x].x!=a&&h[x].x!=0) x=hash(x);
h[x].num++,h[x].x=a;
return;
}
inline int find(int a){
int x=hash(a);
while(h[x].x!=a&&h[x].x!=0) x=hash(x);
return h[x].num;
}
signed main(){
n=in,c=in;
for(int i=1;i<=n;i++){
s[i]=in;
putin(s[i]);
}
for(int i=1;i<=n;i++)
ans+=find(s[i]+c);
printf("%lld",ans);
return 0;
}
T2 P4305 [JLOI2011]不重复数字
P4305 [JLOI2011]不重复数字
题目描述
给出
N
N
N个数,要求把其中重复的去掉,只保留第一次出现的数。
例如,给出的数为
1218331923654
1 2 18 3 3 19 2 3 6 5 4
1218331923654,其中
2
2
2和
3
3
3有重复,去除后的结果为
1218319654
1 2 18 3 19 6 5 4
1218319654。
输入格式
输入第一行为正整数
T
T
T,表示有
T
T
T组数据。
接下来每组数据包括两行,第一行为正整数
N
N
N,表示有
N
N
N个数。第二行为要去重的
N
N
N个正整数。
输出格式
对于每组数据,输出一行,为去重后剩下的数字,数字之间用一个空格隔开。
输入输出样例
输入
2
11
1 2 18 3 3 19 2 3 6 5 4
6
1 2 3 4 5 6
输出
1 2 18 3 19 6 5 4
1 2 3 4 5 6
说明/提示
对于100%的数据,
1
≤
N
≤
50000
,
给
出
的
数
在
32
位
有
符
号
整
数
范
围
内
。
T
≤
50
。
1 \le N \le 50000,给出的数在32位有符号整数范围内。T \le 50。
1≤N≤50000,给出的数在32位有符号整数范围内。T≤50。
思路:
用
h
a
s
h
t
a
b
l
e
hashtable
hashtable判断数是否出现过
代码:
#include<bits/stdc++.h>
using namespace std;
#define in Read()
long long in{
long long s=0,f=1;char x;
for(x=getchar();!isdigit(x);x=getchar()) if(x=='-') f=-1;
for( ;isdigit(x);x=getchar()) s=(s<<1)+(s<<3)+(x&15);
return s*f;
}
const int A=5e5+5;
const int B=2e6+5;
const int mod=1e6+103;
int t;
int n;
long long a[A],r[A],num;
long long head[B],tot;
struct hash_table{
long long nex,val;
}vec[B];
inline long long hash(long long x){
return abs(x%mod+23);
}
inline void putin(long long x){
long long w=hash(x);
vec[++tot]={head[w],x};head[w]=tot;
}
inline bool find(long long x){
long long w=hash(x);
for(int y=head[w];y;y=vec[y].nex){
long long z=vec[y].val;
if(z==x) return true;
}
return false;
}
inline void clean(){
num=0,tot=0;
memset(head,0,sizeof(head));
}
signed main(){
t=in;
while(t--){
clean();
n=in;
for(int i=1;i<=n;i++)
a[i]=in;
for(int i=1;i<=n;i++){
if(!find(a[i])) r[++num]=a[i];
putin(a[i]);
}
for(int i=1;i<=num;i++)
printf("%lld ",r[i]);
printf("\n");
}
return 0;
}