『分治·ST算法』區間最大值和

題解

首先對於區間 [L,R][L,R] 來說,若 ax=max(a[i]),i[l,r]a_x=max(a[i]),i∈[l,r].

xx 的貢獻就是跨過點xx的區間個數×ax\times a_x.

ax×(xL+1)×(Rx+1)a_x\times(x-L+1)\times(R-x+1).

此處的 xxST表求解。

然後分治區間[l,x1][l,x-1]和區間[x+1,R][x+1,R]即可。

代碼如下:

#include <bits/stdc++.h> 

#define int long long

using namespace std;
const int N = 100000;

int n, ans = 0;
int a[N], f[N][30];

void init(void)
{
	for (int i=1;i<=n;++i) f[i][0] = i;
	int t = log2(n);
	for (int j=1;j<=t;++j)
	    for (int i=1;i<=n-(1<<j)+1;++i)
	    {
	        if (a[f[i][j-1]] < a[f[i+(1<<j-1)][j-1]]) 
				f[i][j] = f[i+(1<<j-1)][j-1];
	        else f[i][j] = f[i][j-1];
	    }
	return;
}

int find_max(int l,int r)
{
	int k = log2(r-l+1);
	if (a[f[l][k]] < a[f[r-(1<<k)+1][k]]) 
		return f[r-(1<<k)+1][k];
	return f[l][k];
}

void dfs(int l,int r)
{
	if (l > r) return;
	int x = find_max(l,r);
	ans += a[x]*(x-l+1)*(r-x+1);
	dfs(l,x-1);
	dfs(x+1,r);
	return;
}

signed main(void)
{
	cin>>n;
	for (int i=1;i<=n;++i) 
	    scanf("%lld", a+i);
	init();
	dfs(1,n);
	cout<<ans<<endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章