• [Codeforces Round #622 (Div. 2)]


    [Codeforces Round #622 (Div. 2)] - C2. Skyscrapers (hard version) (单调栈)

    C2. Skyscrapers (hard version)

    time limit per test

    3 seconds

    memory limit per test

    512 megabytes

    input

    standard input

    output

    standard output

    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<iaiai<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

    Copy

    5
    1 2 3 2 1
    

    output

    Copy

    1 2 3 2 1 
    

    input

    Copy

    3
    10 6 8
    

    output

    Copy

    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以及一个数组m。

    让你构建一个数组a满足:

    (1 le a_i le m_i),且不存在这样的情况(j < i < k,a_j > a_i < a_k)

    要求满足上述条件的同事,数组的sum和最大。

    思路:

    我们知道要满足数组的条件,数组必须是一个单峰数组。即我们只需要找到那个数组的峰值的下标即可。

    用单调栈维护两个数组:

    (pre[i])代表从1到(i) 单调不减时最大的前缀和。

    (suf[i])代表从(i)(n) 单调不升时最大的后缀和。

    那么我们找到(pre[i] + suf[i + 1])的最大值下标就是目标数组的峰值下标,然后输出答案即可。

    代码:

    const int maxn = 1000010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    int n;
    ll a[maxn];
    stack<pll> st;
    ll pre[maxn];
    ll suf[maxn];
    
    int main()
    {
    	//freopen("D:\code\text\input.txt","r",stdin);
    	//freopen("D:\code\text\output.txt","w",stdout);
    	n = readint();
    	repd(i, 1, n)
    	{
    		a[i] = readll();
    	}
    	ll sum = 0ll;
    	repd(i, 1, n)
    	{
    		pll temp = mp(a[i], 1ll);
    		while (!st.empty() && temp.fi <= st.top().fi)
    		{
    			pll now = st.top();
    			st.pop();
    			sum -= now.fi * now.se;
    			temp.se += now.se;
    		}
    		st.push(temp);
    		sum += temp.fi * temp.se;
    		pre[i] = sum;
    		// cout << pre[i] << " ";
    	}
    	// cout << endl;
    	while (!st.empty())
    	{
    		st.pop();
    	}
    	sum = 0ll;
    	for (int i = n; i >= 1; --i)
    	{
    		pll temp = mp(a[i], 1ll);
    		while (!st.empty() && temp.fi <= st.top().fi)
    		{
    			pll now = st.top();
    			st.pop();
    			sum -= now.fi * now.se;
    			temp.se += now.se;
    		}
    		st.push(temp);
    		sum += temp.fi * temp.se;
    		suf[i] = sum;
    		// cout << suf[i] << " ";
    	}
    	// cout << endl;
    	ll ans = 0ll;
    	int id;
    	repd(i, 0, n)
    	{
    		if (pre[i] + suf[i + 1] > ans)
    		{
    			ans = pre[i] + suf[i + 1];
    			id = i;
    		}
    	}
    	repd(i, id + 2, n)
    	{
    		a[i] = min(a[i], a[i - 1]);
    	}
    	for (int i = id - 1; i >= 1; --i)
    	{
    		a[i] = min(a[i], a[i + 1]);
    	}
    	repd(i, 1, n)
    	{
    		printf("%lld%c", a[i], i == n ? '
    ' : ' ');
    	}
    
    
    
    
    	return 0;
    }
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    HashSet
    HashMap
    commons-configuration读取配置文件
    JAVA多线程和并发基础面试问答(转载)
    集合
    java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp区别和联系
    七段数码管绘制
    函数的定义与使用
    程序的分支控制
    文本进度条
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/12358016.html
Copyright © 2020-2023  润新知