思路看得题解:
考虑将整个树dfs下来,得到一个括号序列,对于两个点,他们之间的距离就是他们之间的括号数量去掉中间匹配的括号的数量
那么考虑线段树维护,用s表示左括号数量,s2表示右括号数量,
ri li
r
i
l
i
分别表示区间黑点左括号最多的数量/右括号最多的数量,
rm lm
r
m
l
m
分别表示区间到右端点/左端点括号最多的数量,容易发现,当左边放上左括号,右边的区间是随便放左右括号的,当右边的区间放上右括号,左边的区间也是随便发括号的,那么统计即可
复杂度
O(qlogn)
O
(
q
log
n
)
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x; i <= y; ++ i)
#define repd(i,x,y) for(register int i = x; i >= y; -- i)
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
char c;int sign = 1;x = 0;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int N = 3e5+50,inf = 1e9;
int head[N],nxt[N << 1],to[N << 1],tot;
int n,q,sz,w[N],id[N];
inline void add(int x,int y)
{
nxt[tot] = head[x];
to[tot] = y;
head[x] = tot++;
}
struct Segment_tree
{
int ans[N<<2],s[N << 2],s2[N << 2];
int ri[N << 2],rm[N << 2],li[N << 2],lm[N << 2];
inline void update(int id)
{
li[id] = max(li[id<<1],s[id<<1] - s2[id<<1] + li[id<<1|1]);
ri[id] = max(ri[id<<1|1],s2[id<<1|1] - s[id<<1|1] + ri[id<<1]);
lm[id] = max(lm[id<<1],max(s[id<<1] + s2[id<<1] + li[id<<1|1],s2[id<<1] + lm[id<<1|1] - s[id<<1]));
rm[id] = max(rm[id<<1|1],max(s[id<<1|1] + s2[id<<1|1] + ri[id<<1],s[id<<1|1] + rm[id<<1] - s2[id<<1|1]));
ans[id] = max(max(ans[id<<1],ans[id<<1|1]),max(li[id<<1|1] + rm[id<<1],lm[id<<1|1] + ri[id<<1]));
}
void build(int id,int l,int r)
{
if(l == r)
{
if(!w[l]) ri[id] = rm[id] = li[id] = lm[id] = w[l];
else{ ri[id] = li[id] = rm[id] = lm[id] = -inf,ans[id] = -1; if(w[l] == -1) ++s2[id]; else ++ s[id];}
return ;
}
int mid = l + r>> 1;
build(id<<1,l,mid); build(id<<1|1,mid+1,r);
s[id] = s[id<<1|1] + max(0,s[id<<1] - s2[id<<1|1]);
s2[id] = s2[id<<1] + max(0,s2[id<<1|1] - s[id<<1]);
update(id);
}
void modify(int id,int l,int r,int pos)
{
if(l == r)
{
if(w[l]) ri[id] = rm[id]= li[id] = lm[id] = ans[id] = w[l] = 0;
else w[l] = 1,ri[id] = li[id] = rm[id] = lm[id] = -inf,ans[id] = -1;
return ;
}
int mid = l + r>>1;
if(pos <= mid) modify(id<<1,l,mid,pos);
else modify(id<<1|1,mid+1,r,pos);
update(id);
}
}seg;
void dfs(int x,int f)
{
w[++sz] = 1; id[x] = ++ sz;
for(register int i = head[x];~i;i=nxt[i])
if(to[i] != f) dfs(to[i],x);
w[++sz] = -1;
}
char s[2];
int main()
{
memset(head,-1,sizeof head);
read(n);
rep(i,2,n)
{
int u,v;
read(u); read(v);
add(u,v); add(v,u);
}
dfs(1,1);
seg.build(1,1,sz);
read(q);
while(q--)
{
scanf("%s",s);int x;
if(s[0] == 'C') read(x),seg.modify(1,1,sz,id[x]);
if(s[0] == 'G') printf("%d\n",seg.ans[1]);
}
return 0;
}