Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version)

C2. Skyscrapers (hard version)
time limit per test3 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output
This is a harder version of the problem. In this version n≤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 n plots along the highway and is preparing to build n 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 1 to n. Then if the skyscraper on the i-th plot has ai floors, it must hold that ai is at most mi (1≤ai≤mi). Also there mustn’t be integers j and k such that j<iai<ak. Plots j and k are not required to be adjacent to i.

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 n (1≤n≤500000) — the number of plots.

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

Output
Print n integers ai — 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
inputCopy
5
1 2 3 2 1
outputCopy
1 2 3 2 1
inputCopy
3
10 6 8
outputCopy
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] is optimal. Note that the answer of [6,6,8] also satisfies all restrictions, but is not optimal.

題意:
求單峯樓層數最大的序列。

思路:
C1的話數據小可以直接暴力,那麼C2的話就是優化了暴力查找左右邊的第一個比自己小的元素的過程。
具體的話用一個lmi記錄左邊第一個小於自己的元素,rmi記錄右邊第一個比自己小的元素,pre記錄i爲頂峯時的前綴和,suf記錄i爲頂峯時的後綴和,遍歷查找最高峯。

代碼:

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define ll long long
//#define ll unsigned long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-6
#define pi acos(-1)
#define myit set<ll>::iterator
#define mysets multiset<ll>
#define myits multiset<ll>::iterator
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
using namespace std;
inline ll read(){
   ll s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
using namespace std;
ll qpf(ll a, ll b, ll p)
{ll ret = 0;while(b){if(b & 1) ret = (ret + a) % p;
a = (a + a) % p;b >>= 1;}return ret % p ;}
ll qp(ll a, ll n, ll p)
{ll ret = 1;while(n){if(n & 1) ret = qpf(ret, a, p);a = qpf(a, a, p);
n >>= 1;}return ret % p ;}

const int manx=5e5+5;

ll a[manx],b[manx],lmi[manx],rmi[manx],pre[manx],suf[manx];
stack<ll>q;

int main(){
	ll n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=n;i++){
        while(q.size()&&a[q.top()]>=a[i]) q.pop();
        if(q.empty()) lmi[i]=0;
        else lmi[i]=q.top();
        q.push(i);
	}
	while(q.size()) q.pop();
	for(int i=n;i>=1;i--){
        while(q.size()&&a[q.top()]>=a[i]) q.pop();
        if(q.empty()) rmi[i]=n+1;
        else rmi[i]=q.top();
        q.push(i);
	}
	for(int i=1;i<=n;i++){
        if(lmi[i]) pre[i]=pre[lmi[i]]+(i-lmi[i])*a[i];
        else pre[i]=a[i]*i;
	}
	for(int i=n;i>=1;i--){
        if(rmi[i]) suf[i]=suf[rmi[i]]+(rmi[i]-i)*a[i];
        else suf[i]=a[i]*i;
	}
	ll ans=0,index=0;
	for(int i=1;i<=n;i++)
        if(!index || pre[i]+suf[i]-a[i]>ans)
            ans=pre[i]+suf[i]-a[i],index=i;
	ll mx=b[index]=a[index],ma=mx;
	for(int i=index+1;i<=n;i++){
        mx=min(a[i],mx);
        b[i]=mx;
	}
	for(int i=index-1;i>=1;i--){
        ma=min(a[i],ma);
        b[i]=ma;
	}
	for(int i=1;i<=n;i++) cout<<b[i]<<" ";
	return 0;
}

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