题目链接:传送门
题意描述:
给你一个数d和三个数组,让你求triples(i,j,k)——表示|a[i]-b[j]|<=d&&|a[i]-c[k]|<=d&&|b[j]-c[k]|<=d。题目就是要你求有多少组i,j,k满足triples.
题目分析:
如果直接求b数组和c数组中符合(a[i]-d, a[i]+d)的个数,显然是不行的。因为无法满足|b[j]-c[k]|<=d.所以我们先设a[i]、b[j]和c[k]中a[i]最小,那样我们就只有找到bc数组中满足[a[i],a[i]+d]的个数,这样就满足了|b[j]-c[k]|<=d的情况,贡献为b中个数*c中个数。然后依次算b[j]最小和c[k]最小的情况就行了。要注意的是,有可能a[i] 、b[j]和c[k]相等的情况,按上述操作会有重复,所以bc数组的操作和a数组的操作略微不同。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[500005], b[500005], c[500005];
int n, A, B, C;
int main(){
while(scanf("%d %d %d %d", &n, &A, &B, &C) != EOF){
for(int i=0;i<A;++i) scanf("%d", &a[i]);
for(int i=0;i<B;++i) scanf("%d", &b[i]);
for(int i=0;i<C;++i) scanf("%d", &c[i]);
ll ans = 0;
for(int i=0;i<A;++i){
ll cnt1 = upper_bound(b, b+B, a[i]+n) - lower_bound(b, b+B, a[i]);
ll cnt2 = upper_bound(c, c+C, a[i]+n) - lower_bound(c, c+C, a[i]);
ans += cnt1*cnt2;
// cout << cnt1*cnt2 << endl;
}
for(int i=0;i<B;++i){
ll cnt1 = upper_bound(a, a+A, b[i]+n) - upper_bound(a, a+A, b[i]);
ll cnt2 = upper_bound(c, c+C, b[i]+n) - lower_bound(c, c+C, b[i]);
ans += cnt1*cnt2;
// cout << cnt1*cnt2 << endl;
}
for(int i=0;i<C;++i){
ll cnt1 = upper_bound(b, b+B, c[i]+n) - upper_bound(b, b+B, c[i]);
ll cnt2 = upper_bound(a, a+A, c[i]+n) - upper_bound(a, a+A, c[i]);
ans += cnt1*cnt2;
// cout << cnt1*cnt2 << endl;
}
cout << ans << endl;
}
return 0;
}