给定一棵树,每个节点都有自己的权值,对于每个询问,查询x的子树中与x深度差不超过y的节点的最小权值
对树上的每一个节点以深度建立动态线段树,父节点合并子节点的线段树,O(logn)查询
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
const int INF=0x3f3f3f3f;
int n,m,r,a[MAX],ls[MAX<<6],rs[MAX<<6],val[MAX<<6],d[MAX],rt[MAX],cnt;
struct P
{
int to,nxt;
}e[MAX<<1];
int head[MAX],tot;
void init()
{
memset(head,-1,sizeof(head));
memset(val,0,sizeof(val));
memset(rt,0,sizeof(rt));
memset(ls,0,sizeof(ls));
memset(rs,0,sizeof(rs));
tot=0;cnt=0;val[0]=INF;
}
void adde(int u,int v)
{
e[tot].to=v;
e[tot].nxt=head[u];
head[u]=tot++;
}
void update(int &x,int l,int r,int p,int v)
{
x=++cnt;if(l==r){val[x]=v;return;}
int mid=(l+r)>>1;
if(p<=mid) update(ls[x],l,mid,p,v);
else update(rs[x],mid+1,r,p,v);
val[x]=min(val[ls[x]],val[rs[x]]);
}
int merge_(int u,int v)
{
if(!u) return v;
if(!v) return u;
int x=++cnt;
ls[x]=merge_(ls[u],ls[v]);
rs[x]=merge_(rs[u],rs[v]);
if(ls[x]||rs[x]) val[x]=min(val[ls[x]],val[rs[x]]);
else val[x]=min(val[u],val[v]);
return x;
}
int query(int x,int l,int r,int L,int R)
{
if(!x) return INF;
if(l==L&&r==R) return val[x];
int mid=(l+r)>>1;
if(R<=mid) return query(ls[x],l,mid,L,R);
if(L>mid) return query(rs[x],mid+1,r,L,R);
return min(query(ls[x],l,mid,L,mid),query(rs[x],mid+1,r,mid+1,R));
}
void dfs(int u,int fa)
{
update(rt[u],1,100000,d[u],a[u]);
for(int i=head[u];~i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
d[v]=d[u]+1;
dfs(v,u);
rt[u]=merge_(rt[u],rt[v]);
}
}
int main()
{
int x,y;
while(~scanf("%d%d",&n,&r))
{
init();
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
adde(x,y);adde(y,x);
}
d[r]=1;dfs(r,0);
scanf("%d",&m);
int last=0;
while(m--)
{
scanf("%d%d",&x,&y);
x=(x+last)%n+1;y=(y+last)%n;
printf("%d\n",last=query(rt[x],1,100000,d[x],min(100000,d[x]+y)));
}
}
return 0;
}