20150208 WC2015 Day-1
20150209 WC2015 Day0.2

BZOJ1453 [Wc]Dface双面棋盘

laekov posted @ 2015年2月08日 15:07 in 未分类 with tags bzoj ds , 857 阅读

有离线镜像还是能省不少流量。开心。不过流量还是用得飞快啊。

 

这就是个cdq重构的题。学习了前几天xyz大爷讲的扔线段树的做法,省了不少代码。

 

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

using namespace std;

struct node {
	int v, c;
	node *next;
};
struct seg {
	int l, r;
	node *head;
	seg *ls, *rs;
};

const int maxa = 209;
const int maxn = 40009;
const int maxm = 10009;
const int maxnd = maxn * 23;
const int mov[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

#define upmax(_a_,_b_) { \
	if (_a_ < _b_) \
		_a_ = _b_; \
}
#define mkpos(_x_,_y_) (((_x_)<<16)|(_y_))
#define getx(_a_) ((_a_)>>16)
#define gety(_a_) ((_a_)&0x0000ffff)
#define nid(_x_,_y_) (((_x_)*n)+(_y_))

struct disjoint_set {
	int r[maxn], h[maxn];
	int vst[maxn], rst[maxn], ust[maxn], hst[maxn], tst;
	inline disjoint_set() {
		tst = 0;
	}
	void init(int n) {
		for (int i = 0; i < n; ++ i)
			r[i] = i, h[i] = 1;
	}
	int getRoot(int x) {
		for (; r[x] ^ x; x = r[x]);
		return x;
	}
	inline void merge(int u, int v) {
		u = getRoot(u), v = getRoot(v);
		if (h[u] < h[v])
			swap(u, v);
		vst[++ tst] = v;
		rst[tst] = r[v];
		r[v] = u;
		ust[tst] = u;
		hst[tst] = h[u];
		upmax(h[u], h[v] + 1);
	}
	void recover(int x) {
		while (tst > x) {
			r[vst[tst]] = rst[tst];
			h[vst[tst]] = hst[tst];
			-- tst;
		}
	}
};

node nlst[maxnd], *np(nlst);
seg slst[maxn * 3], *sp(slst), *rt;
int n, m, a[maxa][maxa], cc[maxa][maxa], pret[maxa][maxa], ansb[maxm], answ[maxm];

#define midp(_p_) ((_p_->l+_p_->r)>>1)

inline seg* sgtBuild(int l, int r) {
	seg* p(sp ++);
	p-> l = l;
	p-> r = r;
	p-> head = 0;
	if (l + 1 < r) {
		p-> ls = sgtBuild(l, midp(p));
		p-> rs = sgtBuild(midp(p), r);
	}
	return p;
}
inline void sgtIns(seg* p, int l, int r, int ps, int cl) {
	if (p-> l == l && p-> r == r) {
		np-> v = ps;
		np-> c = cl;
		np-> next = p-> head;
		p-> head = np ++;
	}
	else if (r <= midp(p))
		sgtIns(p-> ls, l, r, ps, cl);
	else if (l >= midp(p))
		sgtIns(p-> rs, l, r, ps, cl);
	else {
		sgtIns(p-> ls, l, midp(p), ps, cl);
		sgtIns(p-> rs, midp(p), r, ps, cl);
	}
}

disjoint_set r;

void sgtDfs(seg* p, int cb, int cw) {
	int rp(r. tst);
	for (node* it = p-> head; it; it = it-> next) {
		int x(getx(it-> v)), y(gety(it-> v)), c(it-> c), *v;
		if (c == 0)
			v = &cw;
		else
			v = &cb;
		++ *v;
		cc[x][y] = c;
		for (int mi = 0; mi < 4; ++ mi) {
			int x1(x + mov[mi][0]), y1(y + mov[mi][1]);
			if (x1 < 0 || x1 >= n || y1 < 0 || y1 >= n)
				continue;
			if (cc[x1][y1] == c && r. getRoot(nid(x, y)) != r. getRoot(nid(x1, y1))) {
				-- *v;
				r. merge(nid(x, y), nid(x1, y1));
			}
		}
	}
	if (p-> l + 1 == p-> r) {
		ansb[p-> l] = cb;
		answ[p-> l] = cw;
	}
	else {
		sgtDfs(p-> ls, cb, cw);
		sgtDfs(p-> rs, cb, cw);
	}
	for (node* it = p-> head; it; it = it-> next) {
		int x(getx(it-> v)), y(gety(it-> v));
		cc[x][y] = -1;
	}
	r. recover(rp);
}

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

	scanf("%d", &n);
	for (int i = 0; i < n; ++ i)
		for (int j = 0; j < n; ++ j) {
			scanf("%d", a[i] + j); 
			pret[i][j] = 0;
		}
	scanf("%d", &m);
	rt = sgtBuild(0, m + 1);
	for (int i = 1; i <= m; ++ i) {
		int x, y;
		scanf("%d%d", &x, &y);
		-- x;
		-- y;
		sgtIns(rt, pret[x][y], i, mkpos(x, y), a[x][y]);
		a[x][y] ^= 1;
		pret[x][y] = i;
	}
	for (int i = 0; i < n; ++ i)
		for (int j = 0; j < n; ++ j)
			sgtIns(rt, pret[i][j], m + 1, mkpos(i, j), a[i][j]);
	memset(cc, 0, sizeof(cc));
	r. init(n * n);
	memset(cc, -1, sizeof(cc));
	sgtDfs(rt, 0, 0);
	for (int i = 1; i <= m; ++ i)
		printf("%d %d\n", ansb[i], answ[i]);
}

登录 *


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