【暑训排位赛 #A】Gym - 100971D 单调栈

55 篇文章 0 订阅
7 篇文章 0 订阅

One-dimensional country has n cities, the i-th of which is located at the point x i and has population p i, and all x i, as well as all p i, are distinct. When one-dimensional country got the Internet, it was decided to place the main server in the largest city, and to connect any other city j to the city k that has bigger population than j and is the closest to it (if there are many such cities, the largest one should be chosen). City k is called a parent of city j in this case.

Unfortunately, the Ministry of Communications got stuck in determining from where and to where the Internet cables should be laid, and the population of the country is suffering. So you should solve the problem. For every city, find its parent city.

Input
The first line contains a single integer n (1 ≤ n ≤ 200000) — the number of cities.

Each of the next n lines contains two space-separated integers x i and p i (1 ≤ x i,  p i ≤ 109) — the coordinate and the population of the i-th city.

Output
Output n space-separated integers. The i-th number should be the parent of the i-th city, or  - 1, if the i-th city doesn’t have a parent. The cities are numbered from 1 by their order in the input.

Examples
Input
4
1 1000
7 10
9 1
12 100
Output
-1 4 2 1
Input
3
1 100
2 1
3 10
Output
-1 1 1
Input
3
1 10
3 100
2 1
Output
2 -1 2

题意:每次找到人口最多的城市和最近的人口最多的城市联网,问每个城市是被谁连的

思路:

将题意分析一下,对于一个点,它的父节点就是左边或者右边的大于它的点中,离他最近的那个。(如果同样近就选pi大的)那这样就变成了单调栈的模板题了,维护一个从栈底到栈顶从大到小的栈,每次遇到一个就把栈pop到第一个大于它的元素位置,就是所求的左(右)第一大位置。注意这个时候要先对位置进行离散,排序后顺序遍历就是按照位置大小逐一判断了。记得还要记录一下每个元素在读入的时候的位置,因为输出的时候是按照初始的位置输出。

AC代码:

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 2e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'|ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll n;
map<ll,ll> Map;
ll l[maxn];
ll r[maxn];
ll ans[maxn];
ll pos = 1;
stack<ll> s;
map<ll,ll> Pos;

typedef struct Information
{
    ll id;
    ll val;
    ll dis;
}I;
I a[maxn];

void solve()
{

    a[0].val = a[n+1].val = -1;
    while(!s.empty()) s.pop();
    rep(i,1,n)
    {
        while(s.size()&&a[s.top()].val <= a[i].val) s.pop();
        if(s.empty()) l[i] = 0;
        else l[i] = s.top();
        s.push(i);
    }
    while(!s.empty()) s.pop();
    per(i,n,1)
    {
        while(s.size()&&a[s.top()].val <= a[i].val) s.pop();
        if(s.empty()) r[i] = n+1;
        else r[i] = s.top();
        s.push(i);
    }
    rep(i,1,n)
    {
        if(l[i]==0 && r[i] == n+1) ans[a[i].id]= -1;
        else if(l[i]==0) ans[a[i].id] = a[r[i]].id;
        else if(r[i]==n+1) ans[a[i].id] = a[l[i]].id;
        else
        {
            if(abs(a[l[i]].dis - a[i].dis) < abs(a[r[i]].dis - a[i].dis)) ans[a[i].id] = a[l[i]].id ;
            else if(abs(a[l[i]].dis - a[i].dis) > abs(a[r[i]].dis - a[i].dis)) ans[a[i].id] = a[r[i]].id;
            else
            {
                if(a[l[i]].val > a[r[i]].val) ans[a[i].id] = a[l[i]].id;
                else ans[a[i].id] = a[r[i]].id;
            }
        }
    }
    rep(i,1,n) printf("%lld%c",ans[i], i==n?'\n':' ');
}

int main()
{
    while(cin>>n)
    {
        Map.clear(); Pos.clear();
        rep(i,1,n)
        {
            ll x, val;
            x = read(), val = read();
            Map[x] = val; Pos[x] = i;
        }
        pos = 1;
        for(auto it = Map.begin(); it != Map.end(); it++)
        {
            a[pos].val = it -> se;
            a[pos].dis = it ->fi;
            a[pos++].id = Pos[it->fi];
        }
        solve();

    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值