题目链接:http://codeforces.com/problemset/problem/893/F
题目大意
给定一棵树和根,每个节点上
都有权值,先给定若干个查询(强制在线,要求在题目中)
(x,k),问x节点的子树中其距离x不超过k的节点权值的最小值,
其中x自己规定距离为0.
题目分析
思维蛮巧妙的主席树了,,
我也是参照了别人的思路才恍然大悟,
在数据结构的灵活使用方面还远远不够。。。
主席树本质上就是时间影响的叠加,所以关键是维护的前缀性质和时间序。
考虑对什么建立时间序,在题目中,其实把dp式子列一下就发现,
其影响是随深度变化而转转移的,那么我们试着以深度为时间序,
这里我们要把它映射成单值,详见代码,那么我们往这个时间序里丢的就是
节点数值了,但是什么又是节点的下标呢?以什么建立系来体现
时间关系呢?这里DFS序又被灵活用起来了,,太巧妙了。。。
不难发现我们对于深度d的树,假设我们一直以dfs序的左值建坐标丢值,
那么我们在深度d的树中可以通过节点x的DFS序来查询到,在这个深度之前的
在序区间中的所有点,这样就符合题目建模要求了。
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=2e5+5;
const int inf=1e9+7;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
给定一棵树和根,每个节点上
都有权值,先给定若干个查询(强制在线,要求在题目中)
(x,k),问x节点的子树中其距离x不超过k的节点权值的最小值,
其中x自己规定距离为0.
题目分析:
思维蛮巧妙的主席树了,,
我也是参照了别人的思路才恍然大悟,
在数据结构的灵活使用方面还远远不够。。。
主席树本质上就是时间影响的叠加,所以关键是维护的前缀性质和时间序。
考虑对什么建立时间序,在题目中,其实把dp式子列一下就发现,
其影响是随深度变化而转转移的,那么我们试着以深度为时间序,
这里我们要把它映射成单值,详见代码,那么我们往这个时间序里丢的就是
节点数值了,但是什么又是节点的下标呢?以什么建立系来体现
时间关系呢?这里DFS序又被灵活用起来了,,太巧妙了。。。
不难发现我们对于深度d的树,假设我们一直以dfs序的左值建坐标丢值,
那么我们在深度d的树中可以通过节点x的DFS序来查询到,在这个深度之前的
在序区间中的所有点,这样就符合题目建模要求了。
*/
int n,r,m,x,y,maxv,last;
int a[maxn],v[maxn];
int pl[maxn],pr[maxn],dep[maxn];///DFS序
vector<int> g[maxn];
int rt[maxn],ls[maxn*20],rs[maxn*20],sum[maxn*20],tot=0;
void build(int& o,int l,int r){
o=++tot;
sum[o]=inf;
if(l==r) return;
int mid=l+r>>1;
build(ls[o],l,mid);
build(rs[o],mid+1,r);
}
void update(int& o,int last,int l,int r,int p,int v){
o=++tot;
ls[o]=ls[last],rs[o]=rs[last];
if(l==r) {sum[o]=v;return;}
int mid=l+r>>1;
if(p<=mid) update(ls[o],ls[o],l,mid,p,v);
else update(rs[o],rs[o],mid+1,r,p,v);
sum[o]=min(sum[ls[o]],sum[rs[o]]);
return ;
}
int query(int o,int l,int r,int L,int R){
if(L<=l&&r<=R) return sum[o];
int mid=l+r>>1,ans=inf;
if(L<=mid) ans=min(ans,query(ls[o],l,mid,L,R));
if(mid<R) ans=min(ans,query(rs[o],mid+1,r,L,R));
return ans;
}
///深搜
void dfs(int u,int pre){
pl[u]=++tot;
dep[u]=dep[pre]+1;
maxv=max(maxv,dep[u]);
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(v==pre) continue;
dfs(v,u);
}
pr[u]=tot;
}
///广搜
int vis[maxn],mp[maxn];
void bfs(){
int tmp=0;
queue<int> p;p.push(r);
while(!p.empty()){
int tp=p.front();p.pop();
if(vis[tp]) continue;
else vis[tp]=1;
update(rt[tmp+1],rt[tmp],1,2*n,pl[tp],a[tp]);
mp[dep[tp]]=++tmp;
for(int i=0;i<g[tp].size();i++){
if(vis[g[tp][i]]) continue;
p.push(g[tp][i]);
}
}
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>r;
rep(i,1,n+1) cin>>a[i];
rep(i,1,n){
cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs(r,0);tot=0;
build(rt[0],1,n<<1);
bfs();
cin>>m;
rep(i,0,m){
cin>>x>>y;
x=(x+last)%n+1,y=(y+last)%n;
///cout<<min(dep[x]+y,maxv)<<endl;
last=query(rt[mp[min(dep[x]+y,maxv)]],1,n<<1,pl[x],pr[x]);
cout<<last<<'\n';
}
return 0;
}