Skyscrapers (hard version) (CodeForces-1313C2)(單調棧)

This is a harder version of the problem. In this version n≤500000n≤500000

The outskirts of the capital are being actively built up in Berland. The company "Kernel Panic" manages the construction of a residential complex of skyscrapers in New Berlskva. All skyscrapers are built along the highway. It is known that the company has already bought nn plots along the highway and is preparing to build nn skyscrapers, one skyscraper per plot.

Architects must consider several requirements when planning a skyscraper. Firstly, since the land on each plot has different properties, each skyscraper has a limit on the largest number of floors it can have. Secondly, according to the design code of the city, it is unacceptable for a skyscraper to simultaneously have higher skyscrapers both to the left and to the right of it.

Formally, let's number the plots from 11 to nn. Then if the skyscraper on the ii-th plot has aiai floors, it must hold that aiai is at most mimi (1≤ai≤mi1≤ai≤mi). Also there mustn't be integers jj and kk such that j<i<kj<i<k and aj>ai<akaj>ai<ak. Plots jj and kk are not required to be adjacent to ii.

The company wants the total number of floors in the built skyscrapers to be as large as possible. Help it to choose the number of floors for each skyscraper in an optimal way, i.e. in such a way that all requirements are fulfilled, and among all such construction plans choose any plan with the maximum possible total number of floors.

Input

The first line contains a single integer nn (1≤n≤5000001≤n≤500000) — the number of plots.

The second line contains the integers m1,m2,…,mnm1,m2,…,mn (1≤mi≤1091≤mi≤109) — the limit on the number of floors for every possible number of floors for a skyscraper on each plot.

Output

Print nn integers aiai — the number of floors in the plan for each skyscraper, such that all requirements are met, and the total number of floors in all skyscrapers is the maximum possible.

If there are multiple answers possible, print any of them.

Examples

Input

5
1 2 3 2 1

Output

1 2 3 2 1 

Input

3
10 6 8

Output

10 6 6 

Note

In the first example, you can build all skyscrapers with the highest possible height.

In the second test example, you cannot give the maximum height to all skyscrapers as this violates the design code restriction. The answer [10,6,6][10,6,6] is optimal. Note that the answer of [6,6,8][6,6,8] also satisfies all restrictions, but is not optimal.

 

題意:有n塊地,我們要建造n個大樓,然後建造大樓有條件,一個大樓的左邊和右邊不能都比它高,問你滿足條件的大樓的樓層數。這道題是C1題的升級版本,數據範圍大了很多。
思路:這道題的話,我們要使結果最大,就要每一個都遍歷一遍,因爲數據很大,所以不能使用暴力來做。我們可以用單調棧來維護這個操作。我們依次判斷每座樓爲最高的樓時,所有樓的最大高度之和,記錄最大值最高樓的位置,然後依次得出每座樓的高度。對於每座樓,需要找到它左邊最大高度之和及右邊最大高度之和,那麼需要從最左邊開始,找到第一個比a[i]高的樓a[x],把這之間的樓都變成和a[i]一樣高,即L[i]=L[l[i]]+(ll)(i-l[i])*(ll)a[i];,右側用同樣的方法。最後就可以得到結果。

AC代碼:

#include<bits/stdc++.h>
typedef long long ll;
const int maxx=500010;
const int inf=0x3f3f3f3f;
using namespace std;
int a[maxx];
stack<int> head;
stack<int> tail;
int l[maxx],r[maxx];
ll L[maxx],R[maxx];
int n;
void ddj()
{
    for(int i=1; i<=n; i++)
        cin>>a[i];
    for(int i=1; i<=n; i++)
    {
        while(!head.empty()&&a[head.top()]>=a[i])//找左邊第一個比自己小的
            head.pop();
        if(head.empty())
            l[i]=0;
        else
            l[i]=head.top();
        head.push(i);
    }
    for(int i=n; i>=1; i--)
    {
        while(!tail.empty()&&a[tail.top()]>=a[i])//找右邊第一個比自己小的
            tail.pop();
        if(tail.empty())
            r[i]=n+1;
        else
            r[i]=tail.top();
        tail.push(i);
    }
}
int main()
{
    cin>>n;
    a[0]=0;
    a[n+1]=0;
    ddj();
    memset(L,0,sizeof(L));
    memset(R,0,sizeof(R));
    for(int i=1; i<=n; i++)
        L[i]=L[l[i]]+(ll)(i-l[i])*(ll)a[i];//計算這個數左邊的和
    for(int i=n; i>=1; i--)
        R[i]=R[r[i]]+(ll)(r[i]-i)*(ll)a[i];//計算這個數右邊的和
    ll ans=0,cnt;
    for(int i=1; i<=n; i++)
    {
        if(L[i]+R[i]-a[i]>ans)
        {
            ans=L[i]+R[i]-(ll)a[i];//因爲每一個都多算了一遍
            cnt=i;
        }
    }
    int k=cnt;
    while(k>0)
    {
        for(int i=l[k]+1; i<=k-1; i++)
            a[i]=a[k];
        k=l[k];
    }
    k=cnt;
    while(k<=n)
    {
        for(int i=k+1; i<=r[k]-1; i++)
            a[i]=a[k];
        k=r[k];
    }
    for(int i=1; i<=n; i++)
        cout<<a[i]<<" ";
    cout<<endl;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章