hdu 4605(離線 + dfs + 樹狀數組(好題))

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4605

多校第一場的題,賽後看了題解感覺這題也不是很難, 比賽時忙於別的題目這題都沒看, 還是經驗不足啊, 這道題就是利用dfs結合樹狀數組或者平衡樹(可以支持查找當前集合小於val的元素個數的數據結構)統計從根結點到當前點的一條樹鏈上的權值,向下遞歸時插入回溯時再刪除, 需要把所有查詢離線處理, 每次到達一個節點時先處理和這個點相關的所有查詢, 然後遞歸處理左右兒子節點。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <set>
#include <map>

using namespace std;

#define fi first
#define se second
#define mp make_pair

const int N = 100005;
const int M = N << 1;
int n;

int head[N], to[M], next[M];
int tot;

map<int, int> Map;
vector<pair<int, int> > vec[N];
bool flag[N];
int W[N];

inline int lowbit(int t) {
	return t & (-t);
}

struct BIT {
	int c[N << 2];
	int n;

	void init(int m) { // < m
		this->n = m;
		fill(c, c + n + 1, 0);
	}

	void add(int p, int v) {
		while (p < n) {
			c[p] += v;
			p += lowbit(p);
		}	
	}

	int sum(int m) {
		int res = 0;
		while (m) {
			res += c[m];
			m -= lowbit(m);
		}
		return res;
	}

	bool find(int v) {
		return sum(v) - sum(v - 1) >= 1;	
	}

	void insert(int v) {
		add(v, 1);
	}
	
	void remove(int v) {
		add(v, -1);
	}

	int lower(int v) {
		return sum(v - 1);		
	}

}T1, T2;

void init() {
	for (int i = 1; i <= n; i++) {
		head[i] = -1;
	}
	tot = 0;
}

void add(int u, int v) {
	to[tot] = v, next[tot] = head[u], head[u] = tot++;
}

int a1[N], a2[N], b1[N], b2[N];

void dfs(int u, int L, int R) {
	int sz = vec[u].size();
	pair<int, int> tmp;
	int id, val;
	for (int i = 0; i < sz; i++) {
		tmp = vec[u][i];
		id = tmp.se;
		val = tmp.fi;
		if (T1.find(val) || T2.find(val)) {
			flag[id] = 1;
		}
		else {
			a2[id] = T1.lower(val);
			a1[id] = L - a2[id];
			b2[id] = T2.lower(val);
			b1[id] = R - b2[id];
		}
	}

	for (int i = head[u]; i != -1; i = next[i]) {
		int v = to[i];
		if (i == head[u]) {
			T1.insert(W[u]);
			dfs(v, L + 1, R);
			T1.remove(W[u]);
		}
		else {
			T2.insert(W[u]);
			dfs(v, L, R + 1);
			T2.remove(W[u]);
		}
	}
}

int tmp[N * 2];
pair<int, int> Q[N];
int c;

int main() {
	int test, m, q, u, l, r, v;
	scanf("%d", &test);
	while (test--) {
		scanf("%d", &n);
		init();
		c = 0;
		for (int i = 1; i <= n; i++) {
			scanf("%d", W + i);
			vec[i].clear();
			tmp[c++] = W[i];
		}
		
		scanf("%d", &m);

		while (m--) {
			scanf("%d%d%d", &u, &l, &r);
			add(u, r);
			add(u, l);
		}

		scanf("%d", &q);

		for (int i = 0; i < q; i++) {
			scanf("%d%d", &Q[i].fi, &Q[i].se);
			tmp[c++] = Q[i].se;
			flag[i] = 0;
		}

		sort(tmp, tmp + c);
		c = unique(tmp, tmp + c) - tmp;

		Map.clear();

		for (int i = 0; i < c; i++)
			Map[tmp[i]] = i + 1;

		for (int i = 1; i <= n; i++)
			W[i] = Map[W[i]];
		
		pair<int, int> t;
		for (int i = 0; i < q; i++) {
			t = Q[i];
			vec[t.fi].push_back(mp(Map[t.se], i));
		}
		
		T1.init(c + 1), T2.init(c + 1);
				
		dfs(1, 0, 0);
		
		int x, y;

		for (int i = 0; i < q; i++) {
			if (flag[i]) {
				puts("0");
			}
			else {
				y = a1[i] + 3 * a2[i] + b1[i] + 3 * b2[i];
				x = b2[i];
				printf("%d %d\n", x, y);		
			}
		}
	}
	return 0;
}

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