题解 最近公共祖先
考场上坚持认为树剖可做,于是几乎爆零
别一直坚持一个思路!就算这个思路很可能是对的但自己不会写也要及时换思路!
但正解思路跟考场上想的思路真的很像,连开的数组都一样
考虑一个点被染黑时可能更新哪些白点的答案
开一个bool two[]
和一个int son[]
,两个标记不共存,上翻修改
然后我们需要对一棵子树整体取min
可以按dfs序建一棵线段树,标记永久化
尤其注意id[u]+siz[u]
和id[fa]+siz[fa]-1
的边界即可
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m;
int head[N], size, val[N];
bool black[N];
struct edge{int to, next;}e[N<<1];
inline void add(int s, int t) {edge* k=&e[++size]; k->to=t; k->next=head[s]; head[s]=size;}
namespace force{
int dep[N], lg[N], fa[N][25], sta[N], top;
void dfs(int u, int pa) {
for (int i=1; i<24; ++i)
if (dep[u]>=(1<<i)) fa[u][i]=fa[fa[u][i-1]][i-1];
else break;
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (v!=pa) dep[v]=dep[u]+1, fa[v][0]=u, dfs(v, u);
}
}
int lca(int a, int b) {
if (dep[a]<dep[b]) swap(a, b);
while (dep[a]>dep[b]) a=fa[a][lg[dep[a]-dep[b]]-1];
if (a==b) return a;
for (int i=lg[dep[a]]-1; ~i; --i)
if (fa[a][i]!=fa[b][i])
a=fa[a][i], b=fa[b][i];
return fa[a][0];
}
void solve() {
char t[20];
for (int i=1; i<=n; ++i) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
dep[1]=1;
dfs(1, 0);
for (int i=1,u,ans; i<=m; ++i) {
scanf("%s%d", t, &u);
if (*t=='M') {
if (!black[u]) {black[u]=1; sta[++top]=u;}
}
else {
ans=-1;
for (int j=1; j<=top; ++j)
ans=max(ans, val[lca(u, sta[j])]);
printf("%d\n", ans);
}
}
exit(0);
}
}
namespace task1{
bool two[N];
int son[N], fa[N];
void dfs(int u, int pa) {
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (v!=pa) fa[v]=u, dfs(v, u);
}
}
void solve() {
char t[20];
dfs(1, 0);
for (int i=1,u,ans; i<=m; ++i) {
scanf("%s%d", t, &u);
if (*t=='M') {
if (!black[u]) {
black[u]=1;
int now=fa[u], it=u;
//cout<<"upd "<<u<<endl;
while (now) {
//cout<<"now: "<<now<<' '<<it<<endl;
if (two[now] || son[now]==it) break;
else if (!son[now]) son[now]=it;
else two[now]=1;
it=now, now=fa[now];
}
}
}
else {
ans=-1;
if (son[u] || black[u]) ans=max(ans, val[u]);
int now=fa[u], it=u;
//cout<<"query "<<u<<endl;
while (now) {
//cout<<"now: "<<now<<' '<<it<<endl;
if (two[now] || (son[now]&&son[now]!=it) || black[now]) ans=max(ans, val[now]);
it=now, now=fa[now];
}
printf("%d\n", ans);
}
}
exit(0);
}
}
namespace task{
bool two[N];
int siz[N], id[N], rk[N], son[N], fa[N], tot;
int tl[N<<2], tr[N<<2], maxn[N<<2];
#define tl(p) tl[p]
#define tr(p) tr[p]
#define maxn(p) maxn[p]
void build(int p, int l, int r) {
//cout<<"build "<<p<<' '<<l<<' '<<r<<endl;
tl(p)=l; tr(p)=r;
if (l==r) return ;
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
}
void upd(int p, int l, int r, int dat) {
//scout<<"upd "<<p<<' '<<tl(p)<<' '<<tr(p)<<' '<<l<<' '<<r<<' '<<dat<<endl;
if (l<=tl(p) && r>=tr(p)) {maxn(p)=max(maxn(p), dat); return ;}
int mid=(tl(p)+tr(p))>>1;
if (l<=mid) upd(p<<1, l, r, dat);
if (r>mid) upd(p<<1|1, l, r, dat);
}
int query(int p, int pos) {
if (tl(p)==tr(p)) return maxn(p);
int mid=(tl(p)+tr(p))>>1, ans=maxn(p);
if (pos<=mid) ans=max(ans, query(p<<1, pos));
else ans=max(ans, query(p<<1|1, pos));
return ans;
}
void dfs(int u, int pa) {
siz[u]=1;
id[u]=++tot;
rk[tot]=u;
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (v!=pa) fa[v]=u, dfs(v, u), siz[u]+=siz[v];
}
}
void solve() {
char t[20];
memset(maxn, -1, sizeof(maxn));
dfs(1, 0);
build(1, 1, n);
for (int i=1,x; i<=m; ++i) {
scanf("%s%d", t, &x);
if (*t=='M') {
upd(1, id[x], id[x]+siz[x]-1, val[x]);
int now=fa[x], u=x;
while (now) {
if (two[now] || son[now]==u) break;
else if (!son[now]) {
son[now]=u;
upd(1, id[now], id[u]-1, val[now]);
if (id[u]+siz[u]<=id[now]+siz[now]-1) upd(1, id[u]+siz[u], id[now]+siz[now]-1, val[now]);
}
else two[now]=1, upd(1, id[now], id[now]+siz[now]-1, val[now]);
u=now, now=fa[now];
}
}
else printf("%d\n", query(1, id[x]));
}
exit(0);
}
}
signed main()
{
n=read(); m=read();
for (int i=1; i<=n; ++i) val[i]=read();
for (int i=1,u,v; i<n; ++i) {
u=read(); v=read();
add(u, v); add(v, u);
}
//force::solve();
task::solve();
return 0;
}