您的位置:首页 > 产品设计 > UI/UE

Educational Codeforces Round 33 (Rated for Div. 2) F - Subtree Minimum Query

2017-11-25 21:31 766 查看
F. Subtree Minimum Query

time limit per test6 seconds

memory limit per test512 megabytes

inputstandard input

outputstandard output

You are given a rooted tree consisting of n vertices. Each vertex has a number written on it; number ai is written on vertex i.

Let’s denote d(i,?j) as the distance between vertices i and j in the tree (that is, the number of edges in the shortest path from i to j). Also let’s denote the k-blocked subtree of vertex x as the set of vertices y such that both these conditions are met:

x is an ancestor of y (every vertex is an ancestor of itself);

d(x,?y)?≤?k.

You are given m queries to the tree. i-th query is represented by two numbers xi and ki, and the answer to this query is the minimum value of aj among such vertices j such that j belongs to ki-blocked subtree of xi.

Write a program that would process these queries quickly!

Note that the queries are given in a modified way.

Input

The first line contains two integers n and r (1?≤?r?≤?n?≤?100000) — the number of vertices in the tree and the index of the root, respectively.

The second line contains n integers a1,?a2,?…,?an (1?≤?ai?≤?109) — the numbers written on the vertices.

Then n?-?1 lines follow, each containing two integers x and y (1?≤?x,?y?≤?n) and representing an edge between vertices x and y. It is guaranteed that these edges form a tree.

Next line contains one integer m (1?≤?m?≤?106) — the number of queries to process.

Then m lines follow, i-th line containing two numbers pi and qi, which can be used to restore i-th query (1?≤?pi,?qi?≤?n).

i-th query can be restored as follows:

Let last be the answer for previous query (or 0 if i?=?1). Then xi?=?((pi?+?last)?mod?n)?+?1, and ki?=?(qi?+?last)?mod?n.

Output

Print m integers. i-th of them has to be equal to the answer to i-th query.

Example

input

5 2

1 3 2 3 5

2 3

5 1

3 4

4 1

2

1 2

2 3

output

2

5

题意:对于一个树,问一个点,他的所有距离他k距离的儿子的最小值,强制在线。

做法:主席树,先把树做成一个线段树,线段树里ll[x]到rr[x]之间的节点代表x和他的所有儿子,然后按照节点的深度构建主席树,查询的时候,对于节点i和深度k,找出深度在1到dep[i]+k的节点构成的主席树,然后查询ll[x]到rr[x]之间的最小值。

#include<bits/stdc++.h>
using namespace std;
struct node{
int ls,rs,x;
};
const int N = 1e5+100;
node pt[N*40];
vector<int> G
;
queue<pair<int,int> > que;
int num
,ll
,rr
,root
,dep
,pos
;
bool vis
;
int n,r,md,tot,Time;
void dfs(int x,int f){
ll[x] = ++Time;
int cnt = 1;
for(int i = 0;i < G[x].size();i ++){
int v = G[x][i];
if(v == f) continue;
dfs(v,x);
}
rr[x] = Time;
}
int newnode(){
int rt = tot++;
pt[rt].x = 0;
pt[rt].ls = 0;
pt[rt].rs = 0;
return rt;
}
void build(int &rt,int l,int r){
rt = newnode();
if(l == r){
pt[rt].x = 1e9+100;
return ;
}
int mid = l+r>>1;
build(pt[rt].ls,l,mid);
build(pt[rt].rs,mid+1,r);
pt[rt].x = min(pt[pt[rt].ls].x,pt[pt[rt].rs].x);
}
void update(int &rt,int bef,int x,int d,int l,int r){
rt = newnode();
if(l == r){
pt[rt].x = d;
return ;
}
int mid = l+r>>1;
if(mid >= x){
pt[rt].rs = pt[bef].rs;
update(pt[rt].ls,pt[bef].ls,x,d,l,mid);
}
else{
pt[rt].ls = pt[bef].ls;
update(pt[rt].rs,pt[bef].rs,x,d,mid+1,r);
}
pt[rt].x = min(pt[pt[rt].ls].x,pt[pt[rt].rs].x);
}
void solve(int id,int x,int d){
dep[x] = d;
pos[d] = id;
md = max(md,d);
update(root[id],root[id-1],ll[x],num[x],1,n);
}
int query(int rt,int L,int R,int l,int r){
if(L <= l && R >= r){
return pt[rt].x;
}
int mid = l+r>>1;
int ret = 1e9+100;
if(mid >= L) ret = query(pt[rt].ls,L,R,l,mid);
if(mid < R) ret = min(query(pt[rt].rs,L,R,mid+1,r),ret);
return ret;
}
int main(){
cin >> n >> r;
for(int i= 1;i<= n;i ++) scanf("%d",&num[i]);
for(int i =1;i < n;i ++){
int u,v;
scanf("%d %d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(r,-1);
que.push({r,1});
int cns = 1;
build(root[0],1,n);
vis[r] = true;
while(!que.empty()){
pair<int,int> now = que.front();
que.pop();
solve(cns++,now.first,now.second);
for(int i = 0;i < G[now.first].size();i ++){
int v = G[now.first][i];
if(vis[v]) continue;
vis[v] = true;
que.push({v,now.second+1});
}
}
int m;
cin >> m;
int last = 0;
for(int i =1;i <= m;i ++){
int qi,qk;
scanf("%d %d",&qi,&qk);
qi = (last + qi)%n+1;
qk = (last + qk)%n;
//cout << qi << ' '<< qk <<"!!" << endl;
int rt = dep[qi]+qk;
rt = min(rt,md);
//cout << qi << ' '<< qk << ' '<<dep[pos[rt]] << endl;
last = query(root[pos[rt]],ll[qi],rr[qi],1,n);
printf("%d\n",last);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: