SP11985
这题采用离线处理的方式。
将每个点的点权,以及每次询问的权值分别按从小到大排序。
初始我们有一棵树,每个节点都没有点权。
对于每次询问,将点权小于等于这次询问的权值的点添加上它原本的权值。然后判断一下询问的权值是否等于路径最大值,是则存在,不是则不存在。
这样我们只需要用到单点修改和区间求查询,树剖维护一下即可。
另外注意本题中 \(c\ge 0\),题目可能会询问是否存在点权为 \(0\) 的点,所以不要将节点初始值设为 \(0\)。
int n,m,tot,cnt;
int head[maxn],ans[maxn];
int dfn[maxn],fa[maxn],top[maxn];
int siz[maxn],son[maxn],dep[maxn];
struct edge{int fr,to,nxt;}e[maxn<<1];
struct milk{
int val,pos;
bool operator < (const milk &b) const{
return val<b.val;
}
}t[maxn];
struct ques{
int fr,to,c,pos;
bool operator < (const ques &b) const{
return c<b.c;
}
}q[maxn];
namespace Seg{
#define ls x<<1
#define rs x<<1|1
int maxx[maxn<<2];
void cclear(){
memset(maxx,-1,sizeof maxx);
}
void pushup(int x){
maxx[x]=max(maxx[ls],maxx[rs]);
}
void update(int x,int l,int r,int pos,int val){
if(l==r){
maxx[x]=max(maxx[x],val);
return;
}
int mid=l+r>>1;
if(pos<=mid) update(ls,l,mid,pos,val);
else update(rs,mid+1,r,pos,val);
pushup(x);
}
int query(int x,int l,int r,int L,int R){
if(L<=l&&R>=r) return maxx[x];
int mid=l+r>>1,ans=-1;
if(L<=mid) ans=max(ans,query(ls,l,mid,L,R));
if(R>=mid+1) ans=max(ans,query(rs,mid+1,r,L,R));
return ans;
}
}
namespace Cut{
void dfs1(int u,int fat){
dep[u]=dep[fat]+1;
siz[u]=1;fa[u]=fat;
for(int i=head[u];i;i=e[i].nxt){
int to=e[i].to;
if(to==fat) continue;
dfs1(to,u);siz[u]+=siz[to];
if(siz[son[u]]<siz[to])son[u]=to;
}
}
void dfs2(int u,int tp){
top[u]=tp;dfn[u]=++cnt;
if(son[u]) dfs2(son[u],tp);
for(int i=head[u];i;i=e[i].nxt){
int to=e[i].to;
if(to==fa[u]||to==son[u]) continue;
dfs2(to,to);
}
}
int getmax(int x,int y){
int ans=-1;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=max(ans,Seg::query(1,1,n,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans=max(ans,Seg::query(1,1,n,dfn[x],dfn[y]));
return ans;
}
}
void clear(){
tot=0;cnt=0;Seg::cclear();
memset(head,0,sizeof head);
memset(son,0,sizeof son);
memset(dfn,0,sizeof dfn);
memset(siz,0,sizeof siz);
memset(ans,0,sizeof ans);
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
clear();
for(int i=1;i<=n;i++)
t[i].val=read(),t[i].pos=i;
for(int i=1,fr,to;i<n;i++){
fr=read();to=read();
add(fr,to);add(to,fr);
}
Cut::dfs1(1,0);Cut::dfs2(1,1);
for(int i=1;i<=m;i++)
q[i].fr=read(),q[i].to=read(),
q[i].c=read(),q[i].pos=i;
sort(t+1,t+n+1);sort(q+1,q+m+1);int Now=1;
for(int i=1;i<=m;i++){
while(Now<=n&&t[Now].val<=q[i].c){
Seg::update(1,1,n,dfn[t[Now].pos],t[Now].val);
Now++;
}
ans[q[i].pos]=(Cut::getmax(q[i].fr,q[i].to)==q[i].c);
}
for(int i=1;i<=m;i++) printf(ans[i]?"Find\n":"NotFind\n");
}
return 0;
}