[cf contest 893(edu round 33)] F - Subtree Minimum Query
time limit per test6 secondsmemory limit per test512 megabytesinputstandard inputoutputstandard outputYou 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.
InputThe 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.
OutputPrint m integers. i-th of them has to be equal to the answer to i-th query.
Exampleinput5 2
1 3 2 3 5
2 3
5 1
3 4
4 1
2
1 2
2 3output2
5
我们对于树上的每一个节点开一个线段树(其实是可持久化的)。
每棵线段树都是一个[1..maxdepth]的按照绝对深度来建的线段树。
那么,对于每一个节点x,可以把所以它的子节点的线段树合并到它上面去。
但是这需要可持久化。因为当前节点的信息也要用到。如果不可持久化,可能会导致当前节点的地址在其他线段树里面存在。
实际上,每个地址只存在与一棵线段树中。
然后,由于父子节点之间的线段树只有1条链不同,所以要新建logn个节点。
总共有n-1对父子关系,所以空间为O(nlogn)。
时间复杂度为O(mlogn)。注意强制在线。
code:
View Code1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 typedef long long LL; 5 using namespace std; 6 7 void OJ() { 8 #ifndef ONLINE_JUDGE 9 freopen("in.txt","r",stdin); 10 freopen("out.txt","w",stdout); 11 #endif 12 } 13 14 namespace fastIO { 15 #define gec(c) getchar(c) 16 #define puc(c) putchar(c) 17 char ch; 18 inline int read() { 19 int x=0,f=1; ch=getchar(); 20 while (ch<'0'||ch>'9') { 21 if (ch=='-') f=-f; 22 ch=gec(); 23 } 24 while (ch>='0'&&ch<='9') { 25 x=(x<<3)+(x<<1)+(ch^48); 26 ch=gec(); 27 } 28 return x*f; 29 } 30 int ttt,nnn[20]; 31 template <class T> inline void write(T x) { 32 if (x==0) { 33 puc('0'); return; 34 } 35 if (x<0) x=-x,puc('-'); 36 for (ttt=0; x; x/=10) nnn[++ttt]=x%10; 37 for (; ttt; --ttt) puc(nnn[ttt]+48); 38 } 39 inline void newline () { 40 puc('\n'); 41 } 42 } using namespace fastIO; 43 44 const int N=100005,inf=2e9; 45 int n,q,tot,lim; 46 int a[N],lnk[N],nxt[N<<1],son[N<<1],dep[N]; 47 struct node { 48 node* l,* r; 49 int v; 50 node () { 51 l=r=0; 52 v=inf; 53 } 54 } *ro[N]; 55 #define M ((l)+(r)>>1) 56 inline void refresh (node* c) { 57 c->v=inf; 58 if (c->l) c->v=min(c->v,c->l->v); 59 if (c->r) c->v=min(c->v,c->r->v); 60 } 61 inline void setup (node* &c,int l,int r,int x,int v) { 62 c=new node(); 63 if (l==r) { 64 c->v=v; 65 return; 66 } 67 if (x<=M) setup(c->l,l,M,x,v); 68 else setup(c->r,M+1,r,x,v); 69 refresh(c); 70 } 71 inline node* merge (node* x,node* y) { 72 if (!x||!y) return x?x:y; 73 node* ret=new node(); 74 ret->l=merge(x->l,y->l); 75 ret->r=merge(x->r,y->r); 76 ret->v=min(x->v,y->v); 77 return ret; 78 } 79 inline int reply (node* u,int l,int r,int x,int y) { 80 if (!u) return inf; 81 if (x<=l&&r<=y) return u->v; 82 if (y<=M) return reply(u->l,l,M,x,y); else 83 if (x>M) return reply(u->r,M+1,r,x,y); else 84 return min(reply(u->l,l,M,x,y),reply(u->r,M+1,r,x,y)); 85 } 86 void add (int x,int y) { 87 nxt[++tot]=lnk[x],lnk[x]=tot,son[tot]=y; 88 } 89 void dfs (int x,int p) { 90 setup(ro[x],1,n,dep[x]=dep[p]+1,a[x]); 91 lim=max(lim,dep[x]); 92 for (int j=lnk[x]; j; j=nxt[j]) { 93 if (son[j]==p) continue; 94 dfs(son[j],x); 95 ro[x]=merge(ro[x],ro[son[j]]); 96 } 97 } 98 int main() { 99 OJ(); int x,y,rot,ans=0; 100 n=read(),rot=read(); 101 for (int i=1; i<=n; ++i) { 102 a[i]=read(),ro[i]=0; 103 } 104 for (int i=1; i<n; ++i) { 105 x=read(),y=read(); 106 add(x,y),add(y,x); 107 } 108 dep[0]=lim=0,dfs(rot,0); 109 q=read(); 110 for ( ; q; --q) { 111 x=read(),y=read(); 112 x=(x+ans)%n+1,y=(y+ans)%n; 113 ans=reply(ro[x],1,n,dep[x],min(lim,dep[x]+y)); 114 write(ans),newline(); 115 } 116 return 0; 117 }