hdu 4631(增量最近點對)

題目鏈接

CLJ神犇的題目, 其實這題解法並不難, 算是個經典問題解法的簡單變形吧, 對於最近點對這個問題, 一般有兩種做法, 有一種針對隨機數據很快的O(n ^ 2)解法, 還有一種嚴格O(n * log(n))的分治算法, 對於一般的題目前者會比較快,如果不熟悉這兩種做法可以參考http://www.csie.ntnu.edu.tw/~u91029/PointLinePlane2.html 而這道題目的解法其實就是前種解法的變形,  用一個multiset來維護以x爲關鍵字的有序表, 每次插入一個點之前分情況枚舉更新答案直到不可能更新。。。。


#include <vector>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;

const int N = 500005;

typedef long long LL;
const LL INF = 1LL << 60;

#define DB cout << "Yes" << endl;
#define DB2 cout << "No" << endl;

inline int readint() {
	char c = getchar();
	while (!isdigit(c)) c = getchar();

	int x = 0;
	while (isdigit(c)) {
		x = x * 10 + c - '0';
		c = getchar();
	}

	return x;
}

int buf[10];

inline void writeint(int x) {
	int p = 0;
	if (x == 0) p++;
	else while (x) {
		buf[p++] = x % 10;
		x /= 10;
	}
	for (int j = p - 1; j >= 0; j--)
		putchar('0' + buf[j]);
}

struct Point {
	LL x, y;

	bool operator < (const Point& p) const {
		return x < p.x;
	}
}p[N];

LL dist(const Point& a, const Point& b) {
	return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

multiset<Point> S;
multiset<Point>::iterator it, tmp;

inline LL pow2(int x) {
	return (LL)x * x;
}

int main() {
	int test, ax, bx, cx, ay, by, cy, n;	
	test = readint();

	while (test--) {
		n = readint(), ax = readint(), bx = readint(), cx = readint();
		ay = readint(), by = readint(), cy = readint();

		S.clear();
		p[0].x = 0, p[0].y = 0;

		LL res = 0;
		int m;

		LL d = INF;
		int minX, maxX;

		for (int i = 1; i <= n; i++) {
			p[i].x = (p[i - 1].x * ax + bx) % cx;
			p[i].y = (p[i - 1].y * ay + by) % cy;

			if (i == 1) {
				S.insert(p[i]);
				continue;
			}

			if (d == 0) break;

			minX = S.begin()->x;
			it = S.end();
			it--;
			maxX = it->x;

			if (p[i].x <= minX) {
				for (it = S.begin(); it != S.end(); it++) {
					if (pow2(it->x - p[i].x) >= d) break;
					d = min(dist(*it, p[i]), d);					
				}	
			}
			else if (p[i].x >= maxX) {
				while (1) {
					if (pow2(it->x - p[i].x) >= d) break;
					d = min(dist(*it, p[i]), d);
					if (it == S.begin()) break;
					it--;
				}
			}
			else {
				tmp = S.lower_bound(p[i]);
				for (it = tmp; it != S.end(); it++) {
					if (pow2(it->x - p[i].x) >= d) break;
					d = min(dist(*it, p[i]), d);
				}
				
				if (tmp != S.begin()) {
					it = tmp;
					it--;	
					while (1) {
						if (pow2(it->x - p[i].x) >= d) break;
						d = min(dist(*it, p[i]), d);
						if (it == S.begin()) break;
						it--;
					}
				}				
			}	

			S.insert(p[i]);	
			res += d;
		}

		printf("%I64d\n", res);
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章