P4116 Qtree3

\(\color{#0066ff}{ 题目描述 }\)

给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白

有两种操作:

0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑)

1 v : 询问1到v的路径上的第一个黑点,若无,输出-1

\(\color{#0066ff}{输入格式}\)

第一行 N,Q,表示N个点和Q个操作

第二行到第N行N-1条无向边

再之后Q行,每行一个操作"0 i" 或者"1 v" (1 ≤ i, v ≤ N).

\(\color{#0066ff}{输出格式}\)

对每个1 v操作输出结果。

\(\color{#0066ff}{输入样例}\)

9 8
1 2
1 3
2 4
2 9
5 9
7 9
8 9
6 8
1 3
0 8
1 6
1 7
0 2
1 9
0 2
1 9 

\(\color{#0066ff}{输出样例}\)

-1
8
-1
2
-1

\(\color{#0066ff}{数据范围与提示}\)

For 1/3 of the test cases, N=5000, Q=400000.

For 1/3 of the test cases, N=10000, Q=300000.

For 1/3 of the test cases, N=100000, Q=100000.

\(\color{#0066ff}{ 题解 }\)

树剖||LCT

LCT,维护当前点颜色,和Splay子树颜色有无黑色,平衡树二分就行

#include<bits/stdc++.h>
#define LL long long
LL in() {
	char ch; LL x = 0, f = 1;
	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
	return x * f;
}
const int maxn = 1e5 + 10;
struct LCT {
protected:
	struct node {
		node *ch[2], *fa;
		int col, num, rev;
		node(int col = 0, int num = 0, int rev = 0): col(col), num(num), rev(rev) {
			ch[0] = ch[1] = fa = NULL;
		}
		void trn() { std::swap(ch[0], ch[1]), rev ^= 1; }
		bool ntr() { return fa && (fa->ch[0] == this || fa->ch[1] == this); }
		bool isr() { return this == fa->ch[1]; }
		void upd() {
			num = col;
			if(ch[0]) num |= ch[0]->num;
			if(ch[1]) num |= ch[1]->num;
		}
		void dwn() {
			if(!rev) return;
			if(ch[0]) ch[0]->trn();
			if(ch[1]) ch[1]->trn(); 
			rev = 0;
		}
	}s[maxn], *t[maxn];
	int top;
	void rot(node *x) {
		node *y = x->fa, *z = y->fa;
		int k = x->isr(); node *w = x->ch[!k];
		if(y->ntr()) z->ch[y->isr()] = x;
		x->ch[!k] = y, y->ch[k] = w;
		y->fa = x, x->fa = z;
		if(w) w->fa = y;
		y->upd(), x->upd();
	}
	void splay(node *o) {
		t[top = 1] = o;
		while(t[top]->ntr()) t[top + 1] = t[top]->fa, top++;
		while(top) t[top--]->dwn();
		while(o->ntr()) {
			if(o->fa->ntr()) rot(o->fa->isr() ^ o->isr()? o : o->fa);
			rot(o);
		}
	}
	void access(node *x) {
		for(node *y = NULL; x; x = (y = x)->fa)
			splay(x), x->ch[1] = y, x->upd();
	}
	void makeroot(node *x) { access(x), splay(x), x->trn(); }
	void link(node *x, node *y) { makeroot(x), x->fa = y; }
	void change(node *x) {
		access(x), splay(x);
		x->col ^= 1;
		x->upd();
	}
	node *dfs(node *o) {
		if(o->ch[0]) {
			if(o->ch[0]->num) return dfs(o->ch[0]);
		}
		if(o->col) return o;
		return dfs(o->ch[1]);
	}
	int findans(node *x) {
		makeroot(s + 1), access(x), splay(x);
		if(!x->num) return -1;
		return dfs(x) - s;
	}
public:
	void ins(int n) { for(int i = 1; i < n; i++) link(s + in(), s + in()); }
	void change(int x) { change(s + x); }
	int query(int x) { return findans(s + x); }
}v;
int main() {
	int n = in(), q = in();
	v.ins(n);
	while(q --> 0) {
		if(in()) printf("%d\n", v.query(in()));
		else v.change(in());
	}
	return 0;
}
posted @ 2019-01-13 17:00  olinr  阅读(172)  评论(0编辑  收藏  举报