Gym 100971D Laying Cables 单调栈

Description

One-dimensional country has n cities, the i-th of which is located at the point xi and has population pi, and all xi, as well as all pi, 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 xi and pi(1 ≤ xi,  pi ≤ 109) — the coordinate and the population of thei-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.

Sample Input

41 10007 109 112 100
-1 4 2 1

题意:

   给你n个点在x轴上的位置x和权值pos

  对于一个第i点 他的父亲定义为 和他最近并且 权值大于p[i]的 为点

  输出每个点父亲,没有满足的作其父亲的点输出-1;

题解:

  单调栈预处理出第i个点左边的父亲,和右边的父亲,去最近,权值最大的一个

  作一遍RMQ,二分左边的父亲是谁,最优解是最靠近的点

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+20, M = 1e6+10, mod = 1e9+7, inf = 2e9;
typedef long long ll;

int n,ans[N];
struct ss{long long x,p;int id;}a[N],lefts[N],rights[N];
vector<ss> G;
bool cmp(ss s1,ss s2) {return s1.x<s2.x;}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%I64d%I64d",&a[i].x,&a[i].p),a[i].id = i;
    sort(a+1,a+n+1,cmp);
    a[0].x=-inf, a[0].p = inf; a[0].id = -1;
    G.push_back(a[0]);
    for(int i=1;i<=n;i++) {
        while(G.back().p<=a[i].p) G.pop_back();
        lefts[i]=G.back();
        G.push_back(a[i]);
    }
    G.clear();
    a[n+1] = (ss) {inf,inf,-1};
    G.push_back(a[n+1]);
    for(int i=n;i>=1;i--) {
        while(G.back().p<=a[i].p) G.pop_back();
        rights[i]=G.back();
        G.push_back(a[i]);
    }

    for(int i=1;i<=n;i++) {
        if(abs(lefts[i].x-a[i].x)==abs(rights[i].x-a[i].x)) {
            if(lefts[i].p>rights[i].p) ans[a[i].id] = lefts[i].id;
            else ans[a[i].id] = rights[i].id;
        }
        else if(abs(lefts[i].x-a[i].x)<abs(rights[i].x-a[i].x)) {
           ans[a[i].id] = lefts[i].id;
        }
        else ans[a[i].id] = rights[i].id;
    }
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    printf("\n");
}

单调栈

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+20, M = 1e6+10, mod = 1e9+7, inf = 2e9;
typedef long long ll;

int n;
ll dp[N][19];
int ans[N];

struct ss{long long  x,p;int id;}a[N],lefts[N],rights[N];

bool cmp(ss s1,ss s2) {return s1.x<s2.x;}
ll cal(int l,int r)
{
    if(l==r) return a[l].p;
    int k = (int) (log((double) r-l+1) / log(2.0));
    return max(dp[l][k], dp[r - (1<<k) + 1][k]);
}
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%I64d%I64d",&a[i].x,&a[i].p), a[i].id=i;
    sort(a+1,a+n+1,cmp);
    a[0] = (ss) {-inf,inf,-1};
    a[n+1] = (ss){inf,inf,-1};
      for(int i=0;i<=n+1;i++) dp[i][0] = a[i].p;
    for(int j=1;(1<<j)<=n+1;j++) {
        for(int i=0;i + (1<<j) - 1 <= n+1; i++) {
            if(dp[i][j-1] > dp[i+(1<<(j-1))][j-1])
                dp[i][j] =  dp[i][j-1];
            else {
                 dp[i][j] =  dp[i+(1<<(j-1))][j-1];
            }
        }
    }
    //cout<<cal(0,1)<<endl;
    for(int i=1;i<=n;i++) {
        int l = 0, r = i-1,A=0;
        while(l<=r) {
            int mid = (l+r) >> 1;
            if(cal(mid,i-1)> a[i].p) l = mid+1,A=mid;
            else r = mid-1;
        }
        lefts[i] = a[A];
       // cout<<A<<" ";
        l = i+1, r = n+1;A = n+1;
        while(l<=r) {
            int mid = (l+r) >> 1;
            if(cal(i+1,mid)> a[i].p) r=mid-1,A = mid;
            else l = mid+1;
        }
        rights[i] = a[A];
    //    cout<<A<<endl;
    }

    for(int i=1;i<=n;i++) {
        if(abs(lefts[i].x-a[i].x)==abs(rights[i].x-a[i].x)) {
            if(lefts[i].p>rights[i].p) ans[a[i].id] = lefts[i].id;
            else ans[a[i].id] = rights[i].id;
        }
        else if(abs(lefts[i].x-a[i].x)<abs(rights[i].x-a[i].x)) {
           ans[a[i].id] = lefts[i].id;
        }
        else ans[a[i].id] = rights[i].id;
    }
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    printf("\n");

}

RMQ+二分

时间: 2024-08-18 14:13:49

Gym 100971D Laying Cables 单调栈的相关文章

Code Forces Gym 100971D Laying Cables(单调栈)

D - Laying Cables Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u One-dimensional country has n cities, the i-th of which is located at the point xi and has population pi, and all xi, as well as all pi, are distinct. Whe

Gym 100971D Laying Cables

要求找出每个a[i],找到离他最近而且权值比它大的点,若距离相同,输出权利最大的那个 我的做法有点复杂,时间也要500+ms,因为只要时间花在了map上. 具体思路是模拟一颗树的建立过程,对于权值最大的那个,必须是-1,次大的那个,必须是pos_peo[mx]:就是最大人口的节点id. 然后维护一个单调的序列,记录当前有多少个位置加入了树.用个set保证单调性.小到大 把结构体按人口排序大到小,枚举没个城市,这样保证加入后,后面加入的直接找位置最短即可,人口最对的bigger than now的

Gym 101102D---Rectangles(单调栈)

题目链接 http://codeforces.com/gym/101102/problem/D problem  description Given an R×C grid with each cell containing an integer, find the number of subrectangles in this grid that contain only one distinct integer; this means every cell in a subrectangle

(单调栈)poj-2559 Largest Rectangle in a Histogram

A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the

【单调栈】hdu1506 Largest Rectangle in a Histogram

单调栈的介绍及一些基本性质 http://blog.csdn.net/liujian20150808/article/details/50752861 依次把矩形塞进单调栈,保持其单增,矩形中的元素是一个三元组,存储其位置,高度,以及以其为高度的情况下,大矩形的左边界最多扩展到哪里. 每次将新的元素塞进栈的时候,其左边界就是其左侧第一个小于它的矩形的位置+1. 然后,每个矩形出栈的时候,记录其右边界为当前往栈里面塞的矩形的位置-1,然后更新答案即可. 注意最后把所有的矩形出栈,更新答案. #in

BZOJ 3238 AHOI 2013 差异 后缀数组+单调栈

题目大意: 思路:一看各种后缀那就是后缀数组没跑了. 求出sa,height之后就可以乱搞了.对于height数组中的一个值,height[i]来说,这个值能够作为lcp值的作用域只在左边第一个比他小的位置到右边第一个比他小的位置.这个东西很明显可以倍增RMQ+二分/单调栈. 之后就是数学题了 Σlen[Ti] + len[Tj] = (len + 1) * len * (len - 1),之后吧所有求出来的Σ2 * lcp(Ti,Tj)减掉就是答案. 记得答案开long long CODE:

51nod 1215 数组的宽度&amp;poj 2796 Feel Good(单调栈)

单调栈求每个数在哪些区间是最值的经典操作. 把数一个一个丢进单调栈,弹出的时候[st[top-1]+1,i-1]这段区间就是弹出的数为最值的区间. poj2796 弹出的时候更新答案即可 #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath

[poj3250]单调栈 Bad Hair Day

解题关键:将每头牛看到的牛头数总和转化为每头牛被看到的次数,然后用单调栈求解,其实做这道题的目的只是熟悉下单调栈 此题为递减栈 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<stack> 6 #include<iostream> 7 using namespace std; 8 typedef lo

HDU 5033---Building(单调栈)

题目链接 Problem Description Once upon a time Matt went to a small town. The town was so small and narrow that he can regard the town as a pivot. There were some skyscrapers in the town, each located at position xi with its height hi. All skyscrapers loc