题解:P12180 DerrickLo's City (UBC002C)
分析
直接算吧。先把
所以现在问题变成了一个判定区间内是否存在一对点
求区间
但是这么做会有一点小问题。就是如果我们一共有
这样做的时间复杂度为
代码
il void dfs(int u,int fa){
dep[u]=dep[fa]+1,
f[u][0]=fa;
for(re int i=1;i<20;++i) f[u][i]=f[f[u][i-1]][i-1];
auto it=st.lower_bound(u);
if(it!=st.begin()){
--it;
nxt[*it]=min(nxt[*it],u);
}
it=st.lower_bound(u);
if(it!=st.end()){
pre[*it]=max(pre[*it],u);
}
st.insert(u);
for(auto v:e[u])
if(v!=fa) dfs(v,u);
st.erase(u);
return ;
}
il int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(re int i=19;i>=0;--i) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
for(re int i=19;i>=0;--i) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
il int query_lca(int l,int r){
if(l>r) return l;
int k=__[r-l+1];
if(dep[lc[l][k]]<=dep[lc[r-(1ll<<k)+1][k]]) return lc[l][k];
return lc[r-(1ll<<k)+1][k];
}
il int query_min(int l,int r){
if(l>r) return inf;
int k=__[r-l+1];
return min(Min[l][k],Min[r-(1ll<<k)+1][k]);
}
il int query_max(int l,int r){
if(l>r) return -inf;
int k=__[r-l+1];
return max(Max[l][k],Max[r-(1ll<<k)+1][k]);
}
il void solve(){
n=rd,q=rd;
for(re int i=1;i< n;++i){
int u=rd,v=rd;
e[u].push_back(v),
e[v].push_back(u);
}
for(re int i=1;i<=n;++i) pre[i]=-inf,nxt[i]=inf;
dfs(1,0);
for(re int i=0;i< N;++i) __[i]=log2(i);
for(re int i=1;i<=n;++i){
if(i<n) lc[i][0]=lca(i,i+1);
Min[i][0]=nxt[i],
Max[i][0]=pre[i];
}
for(re int j=1;j<20;++j)
for(re int i=1;i+(1ll<<j)-1<=n;++i){
if(dep[lc[i][j-1]]<=dep[lc[i+(1ll<<(j-1))][j-1]]) lc[i][j]=lc[i][j-1];
else lc[i][j]=lc[i+(1ll<<(j-1))][j-1];
Min[i][j]=min(Min[i][j-1],Min[i+(1ll<<(j-1))][j-1]),
Max[i][j]=max(Max[i][j-1],Max[i+(1ll<<(j-1))][j-1]);
}
while(q--){
int l=rd,r=rd;
if(l==r){
puts("Yes");
continue;
}
int x=query_lca(l,r-1);
if(x<l||x>r){
int mx=query_max(l,r);
int mi=query_min(l,r);
if(mx>=l||mi<=r) puts("No");
else puts("Yes");
}
else{
int Lca;
if(x==l) Lca=query_lca(l+1,r-1);
else if(x==r) Lca=query_lca(l,r-2);
else Lca=lca(query_lca(l,x-2),query_lca(x+1,r-1));
if(Lca==x){
puts("No");
continue;
}
if(dep[Lca]==dep[x]+1&&r-l+1==2){
puts("No");
continue;
}
int mi=min(query_min(l,x-1),query_min(x+1,r));
int mx=max(query_max(l,x-1),query_max(x+1,r));
if(mi<=r||mx>=l) puts("No");
else puts("Yes");
}
}
return ;
}