zoukankan      html  css  js  c++  java
  • [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/ 希望所写的文章对您有帮助。
  • 相关阅读:
    SD卡镜像系列文件(uImage、zImage、dtb、rbf、uboot、preloader)如何更新到SD卡
    printk()打印的信息没办法在终端显示,那怎么调试驱动呢?
    【动态规划】ybt1301 大盗阿福
    【广度优先搜索】ybt1250 The Castle
    【数论/递归】P1017 进制转换
    【深度优先搜索/字符串】P1019 单词接龙
    4-18整理
    【数据结构】用结构体实现并查集
    【数据结构】图论基础整理
    【数据结构】二叉树基本内容整理(一)
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/12358016.html
Copyright © 2011-2022 走看看