zoukankan      html  css  js  c++  java
  • codeforces 1313 C2 Skyscrapers (hard version) (单调队列)

    相较于 easy version ,本题规模扩大到 50w

    考虑优化,
    对于每个高楼,我们要找的其实是最靠近且比这座楼矮的楼,
    中间的楼都建成这座高楼的高度

    所以使用单调队列,求出每座高楼的前缀和与后缀和,
    再扫一遍所有高楼,找到楼高最大的答案

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<stack>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 500010;
    
    int n;
    ll a[maxn],pre[maxn],suf[maxn],p[maxn],q[maxn],b[maxn],l[maxn],r[maxn];
    
    ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
    
    int main(){
    	n = read();
    	for(int i=1;i<=n;++i) a[i] = read();
    	
    	int tail = 0;
    	ll sum = 0;
    	
    	for(int i=1;i<=n;++i){
    		while(q[tail] > a[i] && tail > 0){
    			sum -= 1ll * (p[tail] - p[tail-1]) * q[tail];
    			--tail;
    		}
    		l[i] = p[tail];
    		q[++tail] = a[i];
    		p[tail] = i;
    		sum += 1ll * (p[tail] - p[tail-1]) * a[i];
    		pre[i] = sum;
    	} 
    	
    	tail = 0;
    	sum = 0;
    	memset(q,0,sizeof(q));
    	memset(p,0,sizeof(p));
    	p[0] = n+1;
    	
    	for(int i=n;i>=1;--i){
    		while(q[tail] > a[i] && tail > 0){
    			sum -= 1ll * (p[tail-1] - p[tail]) * q[tail];
    			--tail;
    		}
    		r[i] = p[tail];
    		q[++tail] = a[i];
    		p[tail] = i;
    		
    		sum += 1ll * (p[tail-1] - p[tail]) * a[i];
    		suf[i] = sum - a[i];
    	}
    	
    	ll ans = 0;
    	int pos;
    	
    	for(int i=1;i<=n;++i){
    		if(pre[i] + suf[i] > ans){
    			ans = pre[i] + suf[i];
    			pos = i;
    		}
    	}
    	
    	ll h = a[pos];
    	b[pos] = a[pos];
    	
    	for(int i=pos-1;i>=1;--i){
    		if(a[i] < h) h = a[i];	
    		b[i] = h;
    	}
    	
    	h = a[pos];
    	for(int i=pos+1;i<=n;++i){
    		if(a[i] < h) h = a[i];	
    		b[i] = h;
    	}
    	
    	for(int i=1;i<=n;i++){
    		printf("%lld ",b[i]);
    	}printf("
    ");
    	
    	return 0;
    }
    
  • 相关阅读:
    转:python时间日期处理小结
    vi 的一些常用操作-君子善假于物也
    没有了老师,该如何学习?
    git常用命令
    python 读配置文件
    Python中unittest用法实例
    python 单元测试unnitest-摘录自http://www.cnblogs.com/hackerain/p/3682019.html#undefined
    纯CSS实现立方体旋转
    CSS 3动画
    CSS 2D转换
  • 原文地址:https://www.cnblogs.com/tuchen/p/13818250.html
Copyright © 2011-2022 走看看