题意描述
T组数据,每组给n个数,求n个数中是否有一对数和为m,有输出1没有输出0;
数据范围
n ≤ 1 0 6 , m ≤ 1 0 9 , T ≤ 20 n ≤ 10^6, m ≤ 10^9, T ≤ 20 n≤106,m≤109,T≤20
时间 2s
这题写了五十分暴力,直接判断,
数据是真给力,我没有直接看,不过机房dalao们说数据有1G多,在评测机上一组数据跑了近7s,dalao们在本机上测时基本都是4s多。
我写2s的原因是我本机上std跑了0.4s-.-(不知道他们在电脑上下了什么奇怪的东西),不过后来慢了变成0.7s了,( 我后来写的代码开1s居然跑不过,开2s跑完显示最慢一组也就跑0.75s,脸都黑成这样了QAQ)
题解时间
我们先想一下题中的要求,
给一个组数
a
1
,
a
2
,
a
3
.
.
.
.
.
.
a
n
a_1,a_2,a_3... ...a_n
a1,a2,a3......an
找出一对数
a
i
+
a
j
=
m
a_i + a_j = m
ai+aj=m
a
i
=
m
−
a
j
a_i = m - a_j
ai=m−aj
那么我们只需要找是否存在数
=
m
−
a
j
= m - a_j
=m−aj就行了
这时候我们开数组对每个数进行标记O(n)扫一遍就行。
但是我们会发现数组太大开不下,于是我们就可以权值分块,记录块里的数,然后再扫一遍就行了。
#include<bits/stdc++.h>
#define rg register
#define MAXN 5000010
#define INF 0x3f3f3f3f
#define ll long long
const int N = 40000;
inline void read(int &s){
s = 0; int w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
s *= w; return ;
}
std :: vector<int> block[N];
int n, m, t;
int num, ans = 0;
int cnt[MAXN];
int main()
{
freopen("check.in", "r", stdin);
freopen("check.out", "w", stdout);
read(t);
while(t--){
ans = 0;
read(n), read(m);
num = m / N;
for(int i = 0; i <= num; ++i) block[i].clear();
for(int i = 1; i <= n; ++i){
int a;
read(a);
int b = a % N;
a /= N;
block[a].push_back(b);
}
for(int i = 0; i <= num; ++i){
int l = (m - (i + 1) * N) / N;
int r = (m - i * N) / N;
int bas = l * N;
for(int j = l; j <= r; ++j){
for(int k = 0; k < block[j].size(); ++k){
cnt[block[j][k] + j * N - bas] = 1;
}
}
for (int k = 0; k < block[i].size(); ++k)
{
if (cnt[m - i * N - block[i][k] - bas]){
ans = 1; break;
}
}
for(int j = l; j <= r; ++j){
for (int k = 0; k < block[j].size(); ++k){
cnt[block[j][k] + j * N - bas] = 0;
}
}
if(ans) break;
}
printf("%d\n", ans);
}
return 0;
}