gym 101741 A - Three Arrays 水题

18年暑训 第一题
点我看题
题意 给出三个序列 a,b,c 序列均是从小到大依次排列 问有多少个三元组(i,j,k) 满足
|ai - bj| ≤ d, |ai - ck| ≤ d, and |bj - ck| ≤ d. d 由题目给出
每个序列的最大长度均为5e5。
解题思路:
数据范围为5e5 所以最坏复杂度要控制在nlongn 。
因为是计数问题 所以要考虑如何使计数不重复。
考虑以每个数位最左边点的情况,看有多少种情况满足条件即可,具体逻辑可以看代码。

#include<iostream>
#include<cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAX=1e6+10;
class Node {
public:
    int v,id;
    bool operator < (const Node &b) const {
        if(v==b.v) {
            return id<b.id;
        } else {
            return v<b.v;
        }
    }
    Node(int v,int id):v(v),id(id) {}
    Node() {}
};
int cnt[MAX<<1][3];
Node node[MAX<<1];
int main() {
    int d,n[3];
    while(cin>>d) {
        int tot=0;
        for(int i=0; i<3; i++) {
            cin>>n[i];
        }

        for(int i=0; i<3; i++) {
            int cnt;
            for(int j=1; j<=n[i]; j++) {
                scanf("%d",&cnt);
                node[tot].id=i;
                node[tot].v=cnt;
                tot++;
            }
        }
        sort(node,node+tot);
        for(int i=0; i<tot; i++) {
            for(int j=0; j<3; j++) {
                if(i==0) {
                    cnt[i][j]=0;
                } else {
                    cnt[i][j]=cnt[i-1][j];
                }
            }
            cnt[i][node[i].id]++;
        }
        long long ans=0;
        for(int i=0; i<tot; i++) {
            int v = node[i].v;
            Node tmp = Node(node[i].v+d,4);
            int lx= lower_bound(node,node+tot,tmp)-node-1;
            long long num[3];
            num[node[i].id]=1;
            for(int j=0; j<3; j++) {
                if(j!=node[i].id) {
                    num[j]=cnt[lx][j]-cnt[i][j];
                }
            }
            ans+=num[0]*num[1]*num[2];
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lifelikes/article/details/81071514