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