Three Arrays(二分+贪心)

题目链接:传送门

题意描述:

        给你一个数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;
}

猜你喜欢

转载自blog.csdn.net/weixin_41100093/article/details/87717349