20150311
BZOJ3598 [Scoi2014]方伯伯的商场之旅

BZOJ1604 [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居

laekov posted @ 2015年3月12日 14:47 in 未分类 with tags bzoj ds , 764 阅读

在一道usaco的题上wa了三次。我也是厉害。

 

其实好像有简单做法的。不过我是要脑补一下曼哈顿最小生成树。

 

对于一个平面图上的点的曼哈顿最小生成树,一定存在一种方案,使得每个点的度数至多为8。也就是说以斜率为0,inf,1,-1的四条直线分出来的八个区域里各有一个点就行了。然后是可以保证的。

 

于是就是拿俩树状数组扫四遍就行了。

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

const int inf = 0x3f3f3f3f;

struct point {
	int x, y, i;
	point() {
		x = -inf, y = -1;
	}
	point(int xo, int yo) {
		x = xo, y = yo;
	}
	inline void init(int ix) {
		scanf("%d%d", &x, &y);
		i = ix;
	}
};

inline bool operator <(const point& a, const point& b) {
	return (a. x < b. x) || (a. x == b. x && a. y < b. y);
}

const int maxn = 100009;
const int maxx = 1e9;

int n, c, r[maxn], sz[maxn], cnt, msz;
int v[maxn], tv, w[maxn], tw;
point a[maxn], ta[maxn], tb[maxn];

int getRoot(int x) {
	register int p, q;
	for (p = r[x]; p ^ r[p]; p = r[p]);
	for (; x ^ p; q = r[x], r[x] = p, x = q);
	return x;
}
inline void join(int u, int v) {
	r[getRoot(u)] = getRoot(v);
}

point btQry(point* t, int p) {
	point s(-inf, -1);
	for (++ p; p; p -= (p & -p))
		if (s < t[p])
			s = t[p];
	return s;
}
void btChg(point* t, int p, point v) {
	for (++ p; p < maxn; p += (p & -p))
		if (t[p] < v)
			t[p] = v;
}

inline bool isNeighbour(const point& a, const point& b) {
	return abs(a. x - b. x) + abs(a. y - b. y) <= c;
}

void span() {
	sort(a, a + n);
	tv = tw;
	for (int i = 0; i < n; ++ i) {
		v[i] = a[i]. y - a[i]. x;
		w[i] = - a[i]. x - a[i]. y;
	}
	sort(v, v + n);
	tv = unique(v, v + n) - v;
	sort(w, w + n);
	tw = unique(w, w + n) - w;
	for (int i = 1; i <= tv || i <= tw; ++ i)
		ta[i] = tb[i] = point();
	for (int i = 0; i < n; ++ i) {
		int p(lower_bound(v, v + tv, a[i]. y - a[i]. x) - v);
		point g(btQry(ta, p));
		if (g. y > -1 && isNeighbour(a[i], a[g. y]))
		   join(a[i]. i, a[g. y]. i);	
		btChg(ta, p, point(a[i]. x + a[i]. y, i));
		p = lower_bound(w, w + tw, - a[i]. x - a[i]. y) - w;
		g = btQry(tb, p);
		if (g. y > -1 && isNeighbour(a[i], a[g. y]))
		   join(a[i]. i, a[g. y]. i);	
		btChg(tb, p, point(a[i]. x - a[i]. y, i));
	}
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	scanf("%d%d", &n, &c);
	for (int i = 0; i < n; ++ i) {
		a[i]. init(i);
		r[i] = i;
	}
	span();
	for (int i = 0; i < n; ++ i)
		a[i]. x = maxx - a[i]. x;
	span();
	for (int i = 0; i < n; ++ i)
		swap(a[i]. x, a[i]. y);
	span();
	for (int i = 0; i < n; ++ i)
		a[i]. x = maxx - a[i]. x;
	span();
	memset(sz, 0, sizeof(sz));
	for (int i = 0; i < n; ++ i) {
		if (r[i] == i)
			++ cnt;
		++ sz[getRoot(i)];
	}
	for (int i = 0; i < n; ++ i)
		if (r[i] == i && sz[i] > msz)
			msz = sz[i];
	printf("%d %d\n", cnt, msz);
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter