codeforces-817 D. Imbalanced Array(单调栈)

Posted 为什么他们cf写的这么快

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces-817 D. Imbalanced Array(单调栈)相关的知识,希望对你有一定的参考价值。

题目链接

题意:给定一个数组,要你求数组中每个子序列的的最大值-最小值之和。
思路:考虑每个数的贡献,每个数都会有作为最大值和最小值的时候,只有当a【i】在区间内最为最小值的时候,a【i】都会在最终答案里表示为-a【i】,最大值同理表示为+a【i】,所以思路就变成了求a【i】最为最小值和最大值的区间长度,这个用单调栈来求,L【i】代表a【i】左边第一个大于a【i】的数,R【i】代表a【i】右边第一个大于a【i】的数,于是a【i】最为最小值的区间就是(i-L【i】+1)*(R【i】-i+1),最大值同理。这里有个坑就是有可能答案会算重复。比如1 4 1,第一个1最为最小值的时候会算一个1 4 1,第三个1最为最小值的时候也会算一个1 4 1。只有我们用单调栈来求L【i】的时候保持左开右闭就可以保证只算一次。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
typedef long long ll;
int n,a[maxn],L[maxn],R[maxn],L1[maxn],R1[maxn];
stack<int>s;
int main()

	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	for(int i=1;i<=n;++i)
	
		while(!s.empty()&&a[s.top()]>a[i]) s.pop();
		if(s.size()==0) L[i]=1;
		else L[i]=s.top()+1;
		s.push(i);
	
	while(!s.empty()) s.pop();
	for(int i=n;i>=1;--i)
	
		while(!s.empty()&&a[s.top()]>=a[i]) s.pop();
		if(s.size()==0) R[i]=n;
		else R[i]=s.top()-1;
		s.push(i);
	
	while(!s.empty()) s.pop();
	for(int i=1;i<=n;++i)
	
		while(!s.empty()&&a[s.top()]<a[i]) s.pop();
		if(s.size()==0) L1[i]=1;
		else L1[i]=s.top()+1;
		s.push(i);
	
	while(!s.empty()) s.pop();
	for(int i=n;i>=1;--i)
	
		while(!s.empty()&&a[s.top()]<=a[i]) s.pop();
		if(s.size()==0) R1[i]=n;
		else R1[i]=s.top()-1;
		s.push(i);
	
	ll ans=0;
	for(int i=1;i<=n;++i) 
	ans+=1LL*(i-L1[i]+1)*(R1[i]-i+1)*a[i],
	ans-=1LL*(i-L[i]+1)* (R[i]-i+1)*a[i];
	printf("%lld\\n",ans);

以上是关于codeforces-817 D. Imbalanced Array(单调栈)的主要内容,如果未能解决你的问题,请参考以下文章

codeforces-817 D. Imbalanced Array(单调栈)

codeforces-817 D. Imbalanced Array(单调栈)

Codeforces 817F - MEX Queries

Codeforces 817

Imbalanced Array CodeForces - 817D (思维+单调栈)

Really Big Numbers CodeForces - 817C (数学规律+二分)