(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
", v.query(in()));
else v.change(in());
}
return 0;
}