题意:在一个平面上,每增加一个点,就计算出平面上所有点集中的最近点对的距离的平方,共增加N个点,求每次求出的最近点对的距离平方和,点的给出由 xi = (xi-1 * A x+ Bx) mod Cx,yi = (yi-1 * Ay + By) mod Cy,生成。。
思路:在已有的点集中按X坐标从小到大排序,每增加一个点,找到大于等于它的位置p,然后从右一点一点地计算距离,若>=Min,则退出,因为再加上Y,值是增大的。。然后再从p-1处从右往左计算增加的点与点集中所有点的距离的最小值。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <set>
const long long INF=(1ll<<60);
using namespace std;
struct Point
{
long long x,y;
bool operator <(const Point &e)const
{
return x < e.x;
}
};
int n;
long long x[500010];
long long y[500010];
long long ff()
{
int i;
long long Min = INF, ret = 0;
multiset<Point> se;
se.clear();
Point v;
v.x = x[1];
v.y = y[1];
se.insert(v);
for(i = 2; i <= n; i++)
{
v.x = x[i];
v.y = y[i];
multiset<Point>::iterator p = se.lower_bound(v), iter;
for(iter = p; iter != se.end(); iter++) //从p开始,一直到se.end()前一个位置
{
long long dx = v.x - iter->x;
dx *= dx;
if(dx >= Min) break; //剪枝
long long dy = v.y - iter->y; //一直Wa的原因是我在这里也进行剪枝了。。
dy *= dy;
Min = min(Min, dx + dy);
}
for(iter = p; iter != se.begin();) //从p的上一个位置开始,一直算完se.begin()
{
iter--;
long long dx = v.x - iter->x;
dx *= dx;
if(dx >= Min) break; //剪枝
long long dy = v.y - iter->y;
dy *= dy;
Min = min(Min, dx + dy);
}
ret += Min;
se.insert(v);
}
return ret;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
long long Ax, Bx, Cx,Ay,By,Cy,i;
x[0] = 0;
scanf("%I64d%I64d%I64d%I64d%I64d%I64d", &Ax, &Bx, &Cx,&Ay, &By, &Cy);
for(i = 1; i <= n; i++)
{
x[i] = (x[i-1] * Ax + Bx) % Cx;
}
y[0]=0;
for(i = 1; i <= n; i++)
{
y[i] = (y[i-1] * Ay + By) % Cy;
}
printf("%I64d\n",ff());
}
return 0;
}