题目描述
给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白
有两种操作:
0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑)
1 v : 询问1到v的路径上的第一个黑点,若无,输出-1
输入输出格式
输入格式:
第一行 N,Q,表示N个点和Q个操作
第二行到第N行N-1条无向边
再之后Q行,每行一个操作"0 i" 或者"1 v" (1 ≤ i, v ≤ N).
输出格式:
对每个1 v操作输出结果
输入输出样例
说明
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.
树链剖分模板,我们剖分一下套一个线段树维护每一个点的深度(白点为inf),然后查询inf最小的点编号就好了(我懒用了个pair……)
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5, inf = 0x7fffffff;
struct edge {
int v, next;
}e[maxn << 1];
int head[maxn], cnt, n, a, b, c, t, f, m;
typedef pair<int, int > pii;
char s;
inline char gc(){
static char buf[2000000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 2000000, stdin), p1 == p2) ? EOF : *p1++;
}
inline void read(int & x) {
x = 0; static char c = gc();
while(!isdigit(c)) c = gc();
while(isdigit(c)) x = x * 10 + c - '0', c = gc();
}
void adde(const int &u, const int &v) {
e[++cnt] = (edge) {v, head[u]};
head[u] = cnt;
}
int fa[maxn], son[maxn], size[maxn], id[maxn], d[maxn], top[maxn], idcnt, ord[maxn];
int nstu[maxn];
void dfs1(int u, int p) {
fa[u] = p, d[u] = d[p] + 1;
size[u] = 1;
for(register int i = head[u]; i; i = e[i].next) {
int v = e[i].v;
if(v == p) continue;
dfs1(v, u), size[u] += size[v];
if(size[v] > size[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp) {
top[u] = tp, id[u] = ++idcnt, ord[id[u]] = u;
if(son[u]) dfs2(son[u], tp);
for(register int i = head[u]; i; i = e[i].next) {
int v = e[i].v;
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
namespace SGT {
pii mn[maxn << 2];
int cnt;
void push_up(int rt) {mn[rt] = min(mn[rt << 1], mn[rt << 1 | 1]);}
void build(int l, int r, int rt) {
if(l == r) {mn[rt].first = inf, mn[rt].second = ord[l];return ;}
int mid = l + r >> 1;
build(l, mid, rt << 1), build(mid + 1, r, rt << 1 | 1);
push_up(rt);
}
void edit(int pos, int tl, int tr, int dt, int rt) {
if(tl == tr) {mn[rt].first = dt;return ;}
int mid = tl + tr >> 1;
if(pos <= mid) edit(pos, tl, mid, dt, rt << 1);
else edit(pos, mid + 1, tr, dt, rt << 1 | 1);
push_up(rt);
}
pii query(int l, int r, int tl, int tr, int rt) {
if(l == tl && r == tr) return mn[rt];
int mid = tl + tr >> 1;
if(r <= mid) return query(l, r, tl, mid, rt << 1);
else if(l > mid) return query(l, r, mid + 1, tr, rt << 1 | 1);
else return min(query(l, mid, tl, mid, rt << 1), query(mid + 1, r, mid + 1, tr, rt << 1 | 1));
}
}
#define Q(l, r) query((l), (r), 1, n, 1)
int Gmin(int v) {
using namespace SGT;
pii ans(inf, -1);
while(v) ans = min(ans, Q(id[top[v]], id[v])), v = fa[top[v]];
return ans.second;
}
int main() {
read(n), read(m);
for(register int i = 1; i < n; ++i) {
read(a), read(b);
adde(a, b), adde(b, a);
}
dfs1(1, 0), dfs2(1, 1);
SGT::build(1, n, 1);
for(register int i = 1; i <= m; ++i) {
read(a), read(b);
if(a) printf("%d\n", Gmin(b));
else {
if(nstu[b]) SGT::edit(id[b], 1, n, inf, 1), nstu[b] = 0;
else SGT::edit(id[b], 1, n, d[b], 1), nstu[b] = 1;
}
}
return 0;
}
rockdu
没有帐号? 立即注册