Few people know, but a long time ago a developed state existed on Mars. It consisted of n cities, numbered by integers from 1 to n, the capital had the number 1. Some pairs of cities were connected by a road. The residents of the state were very prudent, therefore, between any two cities, there was exactly one path (possibly consisting of several roads).
Due to the fact that the state was developed, its residents loved traveling. Tourist route on Mars was described by two numbers L and R. This meant that the tourist started the route in the city L, then went to the city L + 1 (without going into the cities, that did not lie on the path between L and L + 1), then went to the city L + 2, and so on. The last city on the route was the city R. A city that was the closest to the capital among all cities visited on this route (if to count a distance between the cities by the roads) was considered the main attraction of the route.
Knowing the map of the Martian state and all the tourist routes, find for each route its main attraction.

Input

The first line contains an integer n that is the number of cities (1 ≤ n ≤ 2 · 105).
The following n − 1 lines describe the roads. Each road is described by two numbers of cities that are connected by it (1 ≤  v i,  u i ≤  nv i ≠  u i).
The ( n + 1)-th line contains an integer q that is the number of tourist routes (0 ≤ q ≤ 10 6).
Then q lines describe the routes themselves. Each route is described by a pair of integers L iR i (1 ≤ L i ≤ R i ≤ n).

Output

Output q integers, one per line — for each route the number of its main attraction. These numbers should be output in the same order in which the respective routes were described.

Example

input output
7
1 2
1 3
2 4
2 5
2 6
3 7
3
4 6
3 4
5 7
2
1
1
7
1 3
3 5
5 6
7 5
1 4
2 4
3
4 5
5 6
6 7
1
5
5

Notes

This problem has a big input and output data size and a strict Time Limit. If you write your solution in C++ we recommend you to use Visual C++ 2013 compiler.

题意就不描述了,是个水题,预处理出i和i+1的lca,然后询问的时候跑线段树就行,这里线段树用到了寻找区间中最小的点的位置,存一下。

懒得改非递归,要手动开栈。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 200010
int n,m;
int v[N<<1],__next[N<<1],first[N],e;
void AddEdge(int U,int V)
{
v[++e]=V;
__next[e]=first[U];
first[U]=e;
}
int fa[N],dep[N],top[N],son[N],siz[N],tot;
void dfs(int U)
{
siz[U]=1;
for(int i=first[U];i;i=__next[i])
if(v[i]!=fa[U])
{
fa[v[i]]=U;
dep[v[i]]=dep[U]+1;
dfs(v[i]);
siz[U]+=siz[v[i]];
if(siz[v[i]]>siz[son[U]])
son[U]=v[i];
}
}
void df2(int U)
{
if(son[U])
{
top[son[U]]=top[U];
df2(son[U]);
}
for(int i=first[U];i;i=__next[i])
if(v[i]!=fa[U]&&v[i]!=son[U])
{
top[v[i]]=v[i];
df2(v[i]);
}
}
int lca(int U,int V)
{
while(top[U]!=top[V])
{
if(dep[top[U]]<dep[top[V]])
swap(U,V);
U=fa[top[U]];
}
if(dep[U]>dep[V])
swap(U,V);
return U;
}
int minv[N<<2];
void update(int p,int v,int rt,int l,int r)
{
if(l==r)
{
minv[rt]=v;
return;
}
int m=(l+r>>1);
if(p<=m) update(p,v,rt<<1,l,m);
else update(p,v,rt<<1|1,m+1,r);
minv[rt]=min(minv[rt<<1],minv[rt<<1|1]);
}
int lcas[N];
int query(int ql,int qr,int rt,int l,int r)
{
if(ql<=l&&r<=qr) return minv[rt];
int m=(l+r>>1),res=2147483647;
if(ql<=m) res=min(res,query(ql,qr,rt<<1,l,m));
if(m<qr) res=min(res,query(ql,qr,rt<<1|1,m+1,r));
return res;
}
int Find2(int v,int rt,int l,int r)
{
if(l==r) return l;
int m=(l+r>>1);
if(minv[rt<<1]==v) return Find2(v,rt<<1,l,m);
else return Find2(v,rt<<1|1,m+1,r);
}
int Findp(int ql,int qr,int v,int rt,int l,int r)
{
if(ql<=l&&r<=qr)
{
if(minv[rt]==v)
return Find2(v,rt,l,r);
return -1;
}
int m=(l+r>>1);
if(ql<=m)
{
int tmp=Findp(ql,qr,v,rt<<1,l,m);
if(tmp!=-1) return tmp;
}
return Findp(ql,qr,v,rt<<1|1,m+1,r);
}
int main()
{
// freopen("j.in","r",stdin);
int x,y;
scanf("%d",&n);
for(int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
AddEdge(x,y);
AddEdge(y,x);
}
top[1]=1;
dfs(1);
df2(1);
for(int i=1;i<n;++i)
{
lcas[i]=lca(i,i+1);
update(i,dep[lcas[i]],1,1,n-1);
}
scanf("%d",&m);
for(int i=1;i<=m;++i)
{
scanf("%d%d",&x,&y);
if(x==y)
printf("%d\n",x);
else
printf("%d\n",lcas[Findp(x,y-1,query(x,y-1,1,1,n-1),1,1,n-1)]);
}
return 0;
}

【最近公共祖先】【线段树】URAL - 2109 - Tourism on Mars的更多相关文章

  1. 「10.19」最长不下降子序列(DP)·完全背包问题(spfa优化DP)·最近公共祖先(线段树+DFS序)

    我又被虐了... A. 最长不下降子序列 考场打的错解,成功调了两个半小时还是没A, 事实上和正解的思路很近了,只是没有想到直接将前$D$个及后$D$个直接提出来 确实当时思路有些紊乱,打的时候只是将 ...

  2. 51 nod 1681 公共祖先 (主席树+dfs序)

    1681 公共祖先 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题   有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另 ...

  3. jzoj4918. 【GDOI2017模拟12.9】最近公共祖先 (树链剖分+线段树)

    题面 题解 首先,点变黑的过程是不可逆的,黑化了就再也洗不白了 其次,对于\(v\)的祖先\(rt\),\(rt\)能用来更新答案当且仅当\(sz_{rt}>sz_{x}\),其中\(sz\)表 ...

  4. hiho #1062 : 最近公共祖先·一(树,最近祖先)

    #1062 : 最近公共祖先·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho最近发现了一个神奇的网站!虽然还不够像58同城那样神奇,但这个网站仍然让小Ho乐在 ...

  5. [LC]235题 二叉搜索树的最近公共祖先 (树)(递归)

    ①题目 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先 ...

  6. [51nod 1681]公共祖先(dfs序+线段树合并)

    [51nod 1681]公共祖先(dfs序+线段树合并) 题面 给出两棵n(n<=100000)个点的树,对于所有点对求它们在两棵树中公共的公共祖先数量之和. 如图,对于点对(2,4),它们在第 ...

  7. 线段树、最短路径、最小生成树、并查集、二分图匹配、最近公共祖先--C++模板

    线段树(区间修改,区间和): #include <cstdio> #include <iostream> #include <cstring> using name ...

  8. 马路 树链剖分/线段树/最近公共祖先(LCA)

    题目 [问题描述] 小迟生活的城市是⼀棵树(树指的是⼀个含有 \(n\) 个节点以及 \(n-1\) 条边的⽆向连通图),节点编号从 \(1\) 到 \(n\),每条边拥有⼀个权值 \(value\) ...

  9. 洛谷P3379 【模板】最近公共祖先(LCA)(树链剖分)

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

随机推荐

  1. Win7命令mklink的使用

    C盘空间越来越小,在Win7里还标红了,心里看得不舒服,得想一些方法腾出一些空间.看了AppData,Chrome占了1G多的空间. 当时安装Chrome浏览器时因为不能指定安装目录,所以Chrome ...

  2. js保存用户名与密码

    <script>   window.onload = function(){     var oForm = document.getElementById('loginForm');   ...

  3. angular js的Inline Array Annotation的理解

    inline Array annotation的形式是: someModule.controller('MyController', ['$scope', 'greeter', function($s ...

  4. 用angular.element实现jquery的一些功能的简单示例

    下面实现了在每个p元素后面自动添加hello world. 在这里我要说的是jquery中的 $document.ready()相当于angualr 中的angualr.element(documen ...

  5. Java之戳中痛点 - (3)三目运算符的两个操作数类型尽量一致

    先看一个例子: package com.test; public class TernaryOperator { public static void main(String[] args) { in ...

  6. 动态规划:状压DP-斯坦纳树

    最小生成树是最小斯坦纳树的一种特殊情况 最小生成树是在给定的点集和边中寻求最短网络使所有点连通 而最小斯坦纳树允许在给定点外增加额外的点,使生成的最短网络开销最小 BZOJ2595 题意是给定一个棋盘 ...

  7. Spring Session使用及源码解析

    参照: http://blog.csdn.net/wojiaolinaaa/article/details/62424642 总结点spring session的一些知识点: spring通过过滤器, ...

  8. [POJ3237]Tree解题报告|树链剖分|边剖

    关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. Tree Description Y ...

  9. 列出top中的pid

    #!/usr/bin/env python import os import string #方法1:通过字符串的isdigits来判断 #filelist = os.listdir('/proc') ...

  10. Opencv 学习笔记之——鼠标,进度条操作

    Opencv中提供一个鼠标调用的函数,SetMouseCallback()函数,它配合一个回调函数来实现鼠标操作的功能.   首先看一下SetMouseCallback的函数原型: c++: void ...