这题非常好!!!
很简单的题目,给一个按照指定节点的树,树上有点权,你需要回答给定节点的子树中,和其距离不超过k的节点中,权值最小的。
肯定首先一想,按照dfs序列建树,然后按照深度为下标,建立主席树,那么我们通过主席树相间得到区间状态,但是很不幸,区间最值不能通过减去历史版本的主席树得到。
考虑照深度建立主席树,按照dfs下标建立,貌似可以耶!!!
我们直接查询当前节点往下k深度的主席树,它保存的就是从深度为1-到深度为deep[p]+k深度的所有节点的dfs序对应的点权值
我们查询子树对应区间的dfs序的最小值,就是答案啦!!!
#include<bits/stdc++.h> #define LL long long using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 1e5+6; struct node{ int l,r; int w; }tree[maxn*40]; struct ID{ int pre,bac; }id[maxn]; int cnt,tot,dfsorder,mxdep; int root[maxn*2]; int a[maxn],deepth[maxn]; int ver[maxn*2],Next[maxn*2],head[maxn]; int mp[maxn*2]; queue<int>q; int n,r; void add(int x,int y){ ver[++tot]=y;Next[tot]=head[x];head[x]=tot; ver[++tot]=x;Next[tot]=head[y];head[y]=tot; } void dfs(int u,int fa){ deepth[u]=deepth[fa]+1; id[u].pre=++dfsorder; mxdep=max(mxdep,deepth[u]); for(int i=head[u];i;i=Next[i]){ int v=ver[i]; if(v==fa)continue; dfs(v,u); } id[u].bac=dfsorder; } void buildtree(int &rt,int l,int r){ rt=++cnt; tree[rt].w=INF; if(l==r){ return ; } int mid=(l+r)>>1; buildtree(tree[rt].l,l,mid); buildtree(tree[rt].r,mid+1,r); } void inserts(int l,int r,int pre,int &now,int pos,int w){ now=++cnt; tree[now]=tree[pre]; tree[now].w=min(tree[now].w,w); if(l==r){ return; } int mid=(l+r)>>1; if(pos<=mid){ inserts(l,mid,tree[pre].l,tree[now].l,pos,w); }else { inserts(mid+1,r,tree[pre].r,tree[now].r,pos,w); } } int query(int rt,int l,int r,int ql,int qr){ if(ql<=l && r<=qr){ return tree[rt].w; } int mid=(l+r)>>1; if (qr<=mid){ return query(tree[rt].l,l,mid,ql,qr); }else if(ql>mid){ return query(tree[rt].r,mid+1,r,ql,qr); }else { return min(query(tree[rt].l,l,mid,ql,mid),query(tree[rt].r,mid+1,r,mid+1,qr)); } } void bfs(int s){ q.push(s); int tmp=0; while(q.size()){ int now=q.front(); q.pop(); inserts(1,2*n,root[tmp],root[tmp+1],id[now].pre,a[now]); mp[deepth[now]]=++tmp; for (int i=head[now];i;i=Next[i]){ int nex=ver[i]; if(deepth[nex]==deepth[now]+1){ q.push(nex); } } } } int main(){ int uu,vv; while(~scanf("%d%d",&n,&r)){ tot=0; cnt=0; dfsorder=0; mxdep=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } buildtree(root[0],1,n*2); for (int i=1;i<=n-1;i++){ scanf("%d%d",&uu,&vv); add(uu,vv); } dfs(r,0); bfs(r); int op; int p,q; int ans=0; scanf("%d",&op); while(op--){ scanf("%d%d",&p,&q); p=(p+ans)%n+1,q=(q+ans)%n; ans=query(root[mp[min(deepth[p]+q,mxdep)]],1,n*2,id[p].pre,id[p].bac); printf("%d\n",ans); } } return 0; }