P6406 [COCI2014-2015#2] Norma


P6406 [COCI2014-2015#2] Norma


曰,口土 了。

\[\sum_{i=1}^N\sum_{j=i}^N(j-i+1) \cdot \min_{p=i}^j\{a_p\} \cdot \max_{q=i}^{j}\{a_q\} \]


心 式子。

反正我也想不出来分治,得题解而借鉴之。

在分治的时候,\([l, mid]\)\([mid+1, r]\) 可以递归得到,那么考虑跨过 \(mid\) 的答案。

记录左边部分的最小值为 \(minn\), 最大值为 \(maxn\)

考虑 \(p, q\)

  • 使得 \(val_{p}\) 恰好小于等于 \(minn\)\(val_{p-1}\) 大于 \(minn\)
  • 使得 \(val_{q}\) 恰好大于等于 \(maxn\)\(val_{q-1}\) 小于 \(maxn\)

那么拆开算呗。

现在假定 \(p \lt q\)

  • 对于区间 \([mid+1, p-1]\) 你就有 \(minn \cdot maxn \cdot \sum_{j = mid + 1}^{p - 1} (j - i + 1)\)
  • 对于区间 \([p, q-1]\) 你就有 \(maxn \cdot \sum_{j=p}^{q-1}(min[j] \cdot (j-i+1)) = maxn \cdot \sum_{j=p}^{q-1}(min[j] \cdot j - min[j] \cdot i + min[j])\)
  • 对于区间 \([q, r]\) 你就有 \(\sum_{j=q}^{r}(min[j] \cdot max[j] \cdot (j-i+1)) = \sum_{j=q}^r (min[j] \cdot max[j] \cdot j - min[j] \cdot max[j] \cdot i + min[j] \cdot max[j])\)

现在假定 \(p \ge q\)

  • 对于区间 \([mid+1, q-1]\) 你就有 \(minn \cdot maxn \cdot \sum_{j = mid + 1}^{q - 1} (j - i + 1)\)
  • 对于区间 \([q, p-1]\) 你就有 \(minn \cdot \sum_{j=q}^{p-1}(max[j] \cdot (j-i+1)) = minn \cdot \sum_{j=q}^{p-1}(max[j] \cdot j - max[j] \cdot i + max[j])\)
  • 对于区间 \([p, r]\) 你就有 \(\sum_{j=p}^{r}(min[j] \cdot max[j] \cdot (j-i+1)) = \sum_{j=p}^r (min[j] \cdot max[j] \cdot j - min[j] \cdot max[j] \cdot i + min[j] \cdot max[j])\)

然后你就知道需要维护 \(min[j], max[j],min[j] \cdot j, max[j] \cdot j, min[j] \cdot max[j], min[j] \cdot max[j] \cdot j\)前缀和

然后馒馒抄式子。

/*
	Name:
	Author: Gensokyo_Alice
	Date:
	Description:
*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;
const ll MAXN = 1e6+10, MOD = 1e9;

ll N, M, ans, val[MAXN], qzminn[MAXN], qzmaxn[MAXN], qzminni[MAXN], qzmaxni[MAXN], qzminnmaxn[MAXN], qzminnmaxni[MAXN];

void mmmm(ll);
ll summ(ll, ll);
void calc(ll, ll);

int main() {
	scanf("%lld", &N);
	for (ll i = 1; i <= N; i++) scanf("%lld", val+i); 
    calc(1, N);
    printf("%lld\n", (ans % MOD + MOD) % MOD);
	return 0;
}

ll summ(ll x, ll y) {return (x + y) * (y - x + 1) / 2 % MOD;}
void mmmm(ll x) {ans = ans + x + MOD >= MOD ? ans + x - MOD : ans + x;}

void calc(ll l, ll r) {
	if (l == r) {
		mmmm(val[l] * val[l] % MOD);
		return ;
	}
	ll mid = (l + r) >> 1;
	calc(l, mid); calc(mid + 1, r);
	ll maxn = 0, minn = MOD;
	qzminn[mid] = qzmaxn[mid] = qzminni[mid] = qzmaxni[mid] = qzminnmaxn[mid] = qzminnmaxni[mid] = 0;
	for (ll i = mid + 1; i <= r; i++) {
		maxn = max(maxn, val[i]), minn = min(minn, val[i]);
		qzminn[i] = (qzminn[i-1] + minn) % MOD;
		qzmaxn[i] = (qzmaxn[i-1] + maxn) % MOD;
		qzminni[i] = (qzminni[i-1] + minn * i % MOD) % MOD;
		qzmaxni[i] = (qzmaxni[i-1] + maxn * i % MOD) % MOD;
		qzminnmaxn[i] = (qzminnmaxn[i-1] + minn * maxn % MOD) % MOD;
		qzminnmaxni[i] = (qzminnmaxni[i-1] + minn * maxn % MOD * i % MOD) % MOD;
	}
	minn = MOD, maxn = 0;
	for (ll p = mid + 1, q = mid + 1, i = mid; i >= l; i--) {
		minn = min(minn, val[i]), maxn = max(maxn, val[i]);
		while (p <= r && val[p] > minn) p++;
		while (q <= r && val[q] < maxn) q++;
		if (p < q) {
			mmmm(minn * maxn % MOD * summ(mid - i + 2, p - i) % MOD);
			mmmm(maxn * ((qzminni[q-1] - qzminn[q-1] * i % MOD + qzminn[q-1]) - (qzminni[p-1] - qzminn[p-1] * i % MOD + qzminn[p-1])) % MOD);
			mmmm(((qzminnmaxni[r] - qzminnmaxn[r] * i % MOD + qzminnmaxn[r]) - (qzminnmaxni[q-1] - qzminnmaxn[q-1] * i % MOD + qzminnmaxn[q-1])) % MOD);
		} else {
			mmmm(minn * maxn % MOD * summ(mid - i + 2, q - i) % MOD);
			mmmm(minn * ((qzmaxni[p-1] - qzmaxn[p-1] * i % MOD + qzmaxn[p-1]) - (qzmaxni[q-1] - qzmaxn[q-1] * i % MOD + qzmaxn[q-1])) % MOD);
			mmmm(((qzminnmaxni[r] - qzminnmaxn[r] * i % MOD + qzminnmaxn[r]) - (qzminnmaxni[p-1] - qzminnmaxn[p-1] * i % MOD + qzminnmaxn[p-1])) % MOD);
		}
	}
}