题意:给出N个村庄,第i个村庄编号为i,坐标为xi,人数为p[i],要求输出每个村庄离自己最近的,人数比自己多的村庄编号,若有一样,输出人数较多的那个。
思路:用单调栈处理出每个村庄左边和右边最近的,比自己人多的村庄编号即可。
# include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+3;
struct node
{
int p, v, id;
bool operator < (const node &a)const
{
return p < a.p;
}
}a[maxn];
int l[maxn], r[maxn], que[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=1; i<=n; ++i)
scanf("%d%d",&a[i].p, &a[i].v), a[i].id = i;
sort(a+1, a+n+1);
memset(que, 0, sizeof(que));
int h=0, t=0;
for(int i=1; i<=n; ++i)
{
int tmp = a[i].v;
while(t>h && a[que[t]].v<=tmp) --t;
if(t>h) l[i]=que[t];
else l[i]=-1;
que[++t] = i;
}
memset(que, 0, sizeof(que));
h = t = 0;
for(int i=n; i>=1; --i)
{
int tmp = a[i].v;
while(t>h && a[que[t]].v<=tmp) --t;
if(t>h) r[i]=que[t];
else r[i]=-1;
que[++t] = i;
}
for(int i=1; i<=n; ++i)
{
if(l[i]==-1 && r[i]==-1) que[a[i].id] = -1;
else if(l[i]==-1) que[a[i].id] = a[r[i]].id;
else if(r[i]==-1) que[a[i].id] = a[l[i]].id;
else if(a[i].p-a[l[i]].p>a[r[i]].p-a[i].p) que[a[i].id] = a[r[i]].id;
else if(a[i].p-a[l[i]].p<a[r[i]].p-a[i].p) que[a[i].id] = a[l[i]].id;
else if(a[l[i]].v > a[r[i]].v) que[a[i].id] = a[l[i]].id;
else que[a[i].id] = a[r[i]].id;
}
for(int i=1; i<=n; ++i)
printf("%d ",que[i]);
puts("");
return 0;
}