noi.ac #42 模拟

(des)
二维平面上存在 (m) 个点,每个点会对该点的 (8) 个方向上的最近的点产生影响
问每个点会被影响多少次

(sol)
过每个点会产生 (4) 条线段
保存每条线段的斜率与截距
从平面的左上方向右下方扫描
判断每个点产生的 (4) 个斜率与截距是否存在
在遍历中更新该方向上的最后一次的斜率与截距
并且正反方向统计答案

(code)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>

#define Pair pair<int, int> 
using namespace std;
const int N = 1e5 + 10, Inf = (1 << 30);

#define Rep(i, a, b) for(int i = a; i <= b; i ++)

int Answer[10];
int Ans[N];

map <Pair, int> Map;

#define gc getchar()

inline int read() {
	int x = 0; char c = gc;
	while(c < '0' || c > '9') c = gc;
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
	return x;
}

struct Node {
	int X, Y, K[5], B[5], id;
	bool operator < (const Node a) const {
		if(this-> Y == a.Y) return this-> X < a.X;
		return this-> Y > a.Y;
	}
} A[N];

int n, m;

void Get(Node &a) {
	int x = a.X, y = a.Y;
	a.K[1] = 1, a.B[1] = y - x;
	a.K[2] = -1, a.B[2] = x + y;
	a.K[3] = Inf, a.B[3] = x; // 上 
	a.K[4] = y, a.B[4] = Inf; // 左 
}

int main() {
	n = read(), m = read();
	Rep(i, 1, m) {
		A[i].X = read(), A[i].Y = read(); 
		Get(A[i]);
	}
	sort(A + 1, A + m + 1);
	Rep(i, 1, m) {
		Rep(j, 1, 4) {
			Pair now; now.first = A[i].K[j];
			now.second = A[i].B[j];
			if(Map[now]) {
				int pre = Map[now];
				Ans[pre] ++;
				Ans[i] ++;
				Map[now] = i;
			} else {
				Map[now] = i;
			}
		} 
	}
	Rep(i, 1, m)
		Answer[Ans[i]] ++;
	Rep(i, 0, 8)
		printf("%d ", Answer[i]);
	return 0;
} 
原文地址:https://www.cnblogs.com/shandongs1/p/9698132.html