Loading

luogu P6503 [COCI 2010/2011 #3] DIFERENCIJA

题目大意

题面
让我们求一个序列中的

\[\sum^{n}_{i=1}\sum^{n}_{j=i}(\max_{i\leq k\leq j} a_k-\min_{i\leq k \leq j} a_k) \]

Sol

由于暴力是\(O(n^2)\)的,所以我们需要优化
我们先看暴力的流程:

  • 每次选取一段区间求出其中的最大最小值(可以使用滑动窗口控制右端点)
  • 随后计算答案

复杂度瓶颈主要在于对于每一个右端点都要处理一次
我们把原式拆开:

\[\sum^{n}_{i=1}\sum^{n}_{j=i}\max_{i\leq k\leq j} a_k-\sum^{n}_{i=1}\sum^{n}_{j=i}\min_{i\leq k \leq j} a_k \]

看起来求最大值和最小值的方法是一致的,所以我们先考虑求最大值
对于每一个\(a_i\),我们一定能找到一个最大的区间\([l,r]\)满足\(\max_{l\leq k\leq r} a_k=a_i\)
这个时候就存在\((i-l+1)(r-i+1)\)个区间最大值为\(a_i\) (可以参考左边选几个 右边选几个理解,左右可以不选)
如果要直接维护一个数的区间,复杂度依然不对
转换一下,既然这个区间是最大的,那么说明\(a_{l-1}\)\(a_{r+1}\)一定是大于等于\(a_i\)的 (至于为什么大于等于待会说)
这个时候就变成了单调栈的模板,维护一个数左边第一个比他大的数的位置
上面个区间个数就可以变成\((i-L)(R-i)\) ,其中\(L\)为左边第一个大于它的数,\(R\)为右边第一个大于等于它的数
一边取等于一边不取是因为不会产生重复贡献 (考虑一下 \(1,0,1,0,1\)的情况)
(也可以左边取右边不取)

最小值同理,整体复杂度是\(O(n)\),可以AC

Code

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 3e5+10;

int n;
LL a[N];
LL ss[N] , hh , tt;
LL lmax[N] , rmax[N] , lmin[N] , rmin[N];

int main() {
	scanf("%d" , &n);
	for(int i = 1 ; i <= n ; i ++)
		scanf("%lld" , &a[i]);
	
	hh = 0; tt = -1;
	for(int i = 1 ; i <= n ; i ++) {
		while(hh <= tt && a[ss[tt]] <= a[i]) tt --;
		if(hh <= tt) lmax[i] = ss[tt];
		
		ss[++ tt] = i;
	}
	
	hh = 0; tt = -1;
	for(int i = 1 ; i <= n ; i ++) {
		while(hh <= tt && a[ss[tt]] >= a[i]) tt --;
		if(hh <= tt) lmin[i] = ss[tt];
		
		ss[++ tt] = i;
	}
	
	hh = 0; tt = -1;
	for(int i = n ; i >= 1 ; i --) {
		while(hh <= tt && a[ss[tt]] < a[i]) tt --;
		if(hh <= tt) rmax[i] = ss[tt];
		else rmax[i] = n+1;
		
		ss[++ tt] = i;
	}
	
	hh = 0; tt = -1;
	for(int i = n ; i >= 1 ; i --) {
		while(hh <= tt && a[ss[tt]] > a[i]) tt --;
		if(hh <= tt) rmin[i] = ss[tt];
		else rmin[i] = n+1;
		
		ss[++ tt] = i;
	}
	
	LL res = 0;
	for(int i = 1 ; i <= n ; i ++) {
		res += a[i] * (i - lmax[i]) * (rmax[i] - i);
		res -= a[i] * (i - lmin[i]) * (rmin[i] - i);
	}
	printf("%lld\n" , res);
	return 0;
}
posted @ 2025-10-01 11:00  lyr2023  阅读(4)  评论(0)    收藏  举报