BZOJ3351 [ioi2009]Regions

ioi的数据结构题,果然还是比较BT的。

 

做法是对颜色分开,大的颜色预处理,小的颜色直接暴力。

 

然后一个小错又坑了好久。我真的没救了。

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

using namespace std;

const int buf_len = 4000;
const size_t buf_size = buf_len * sizeof(char);
char buf[buf_len], *bufb(buf), *bufe(buf + 1);
#define readBuf() { \
	if (++ bufb == bufe) \
		bufe = (bufb = buf) + fread(buf, 1, buf_size, stdin); \
}
#define readInt(_x_) { \
	register int _s_(0); \
	do { \
		readBuf(); \
	} while (!isdigit(*bufb)); \
	do { \
		_s_ = _s_ * 10 + *bufb - 48; \
		readBuf(); \
	} while (isdigit(*bufb)); \
	_x_ = _s_; \
}

struct edge {
	int t;
	edge *next;
};
typedef pair <int, int> ninfo;
typedef long long dint;

#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif

const int maxn = 200009;
const int maxb = 259;
const int maxbn = 800;
const int maxc = 25009;

int n, r, q, c[maxn], bi[maxc], bc[maxn], nod[maxn];
int dfb[maxn], dfe[maxn], dfo[maxn];
dint bn[maxb][maxc], nb[maxb][maxc];
edge *head[maxn], elst[maxn], *ep(elst);
ninfo ni[maxn], ci[maxn];

struct bin_tree {
	int a[maxn], t[maxn], c;
	bin_tree() {
		c = 0;
		memset(t, 0, sizeof(t));
	}
	void chg(int p, int v) {
		for (; p <= n; p += (p & -p))
			if (t[p] < c)
				t[p] = c, a[p] = v;
			else
				a[p] += v;
	}
	int qry(int p) {
		int s(0);
		for (; p; p -= (p & -p))
			if (t[p] == c)
				s += a[p];
		return s;
	}
};

bin_tree bt;

inline void addEdge(int u, int v) {
	ep-> t = v;
	ep-> next = head[u];
	head[u] = ep ++;
}

void buildTree() {
	static int stc[maxn];
	int tst(1), dfn(0);
	stc[1] = 1;
	while (tst) {
		int p(stc[tst --]);
		dfo[dfb[p] = dfe[p] = ++ dfn] = p;
		for (edge* e = head[p]; e; e = e-> next)
			stc[++ tst] = e-> t;
	}
	for (int ti = n; ti; -- ti) {
		int p(dfo[ti]);
		for (edge* e = head[p]; e; e = e-> next)
			if (dfe[e-> t] > dfe[p])
				dfe[p] = dfe[e-> t];
	}
}

void preAns() {	
	static int ca[maxn], cb[maxn];
	memset(bn, 0, sizeof(bn));
	memset(nb, 0, sizeof(nb));
	for (int i = 1; i <= n; ++ i)
		ni[i - 1] = ninfo(c[i], i);
	sort(ni, ni + n);
	memset(cb, 0, sizeof(cb));
	memset(bi, -1, sizeof(bi));
	int tb(0);
	for (int i = 0, j; i < n; i = j) {
		for (j = i; j < n && ni[j]. first == ni[i]. first; ++ j)
			nod[j] = ni[j]. second;
		bc[ni[i]. first] = i;
		ci[tb ++] = ninfo(i - j, ni[i] .first);
	}
	sort(ci, ci + tb);
	for (int ti = 0; ti < tb && ti < maxb; ++ ti) {
		int i(bc[ci[ti]. second]), j(i - ci[ti]. first);
		bi[ni[i]. first] = ti;
		memset(ca, 0, sizeof(ca));
		memset(cb, 0, sizeof(cb));
		for (int k = i; k < j; ++ k) {
			++ ca[dfb[nod[k]]];
			++ cb[dfb[nod[k]]];
			-- cb[dfe[nod[k]] + 1];
		}
		for (int k = 1; k <= n; ++ k)
			ca[k] += ca[k - 1], cb[k] += cb[k - 1];
		for (int p = 1; p <= n; ++ p) {
			nb[ti][c[p]] += ca[dfe[p]] - ca[dfb[p] - 1];
			bn[ti][c[p]] += cb[dfb[p]];
		}
	}
}

dint query(int r1, int r2) {
	dint ans(0);
	++ bt. c;
	for (int i = bc[r2]; i < n && c[nod[i]] == r2; ++ i)
		bt. chg(dfb[nod[i]], 1);
	for (int i = bc[r1]; i < n && c[nod[i]] == r1; ++ i)
		ans += bt. qry(dfe[nod[i]]) - bt. qry(dfb[nod[i]] - 1);
	return ans;
}

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

	readInt(n);
	readInt(r);
	readInt(q);
	readInt(c[1]);
	memset(head, 0, sizeof(head));
	for (int i = 2; i <= n; ++ i) {
		int u;
		readInt(u);
		readInt(c[i]);
		addEdge(u, i);
	}
	buildTree();
	preAns();
	while (q --) {
		int r1, r2;
		readInt(r1);
		readInt(r2);
		if (bi[r1] > -1)
			printf(lld "\n", bn[bi[r1]][r2]);
		else if (bi[r2] > -1)
			printf(lld "\n", nb[bi[r2]][r1]);
		else
			printf(lld "\n", query(r1, r2));
	}
}