解法:根据题意用单调栈维护可以看见的最右边的山峰,连边建树,对于每次询问,其实就是找两个节点的LCA,这个可以用tarjan一次性处理完。
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
using namespace std;
#define fst first
#define snd second
const int maxn=100005;
typedef unsigned int uii;
typedef long long ll;
typedef pair<int,int> pii;
int n,m,top,res[maxn],f[maxn];
ll x[maxn],y[maxn],a,b,x1,x2,y1,y2;
struct ss {
ll x,y;
int id;
ss(){}
ss(ll x,ll y,int id):x(x),y(y),id(id){}
} stk[maxn];
vector<int> vec[maxn];
vector<pii> que[maxn];
int F(int x) {
return x==f[x]?x:f[x]=F(f[x]);
}
void dfs(int u) {
f[u]=u;
for (uii i=0;i<vec[u].size();++i) {
int v=vec[u][i];
dfs(v);
f[v]=u;
}
for (uii i=0;i<que[u].size();++i) {
int v=que[u][i].fst;
if (f[v]!=-1)
res[que[u][i].snd]=F(v)+1;
}
}
int main()
{
scanf("%d",&n);
for (int i=0;i<n;++i)
scanf("%lld%lld",&x[i],&y[i]);
scanf("%d",&m);
for (int i=0;i<m;++i) {
scanf("%lld%lld",&a,&b);
--a;
--b;
que[a].push_back(pii(b,i));
que[b].push_back(pii(a,i));
}
stk[++top]=ss(x[n-1],y[n-1],n-1);
for (int i=n-2;i>=0;--i) {
while (top>=2) {
x2=stk[top].x,y2=stk[top].y;
x1=stk[top-1].x,y1=stk[top-1].y;
if ((y1-y2)*(x2-x[i])>(y2-y[i])*(x1-x2))
--top;
else
break;
}
vec[stk[top].id].push_back(i);
stk[++top]=ss(x[i],y[i],i);
}
memset(f,-1,sizeof f);
dfs(n-1);
for (int i=0;i<m;++i)
printf("%d\n",res[i]);
return 0;
}