原题链接:https://acm.hdu.edu.cn/showproblem.php?pid=6989
题意
给你一个数列,定义一个区间的平均值为(Max+Min)/2,询问一个区间的所有平均值的期望是多少。
分析
我们把题目的式子化简一下,就是
∑
m
a
x
+
∑
m
i
n
2
∗
l
e
n
∗
(
l
e
n
+
1
)
2
\frac{\sum max+\sum min}{2*\frac{len*(len+1)}{2}}
2∗2len∗(len+1)∑max+∑min
=
∑
m
a
x
+
∑
m
i
n
l
e
n
∗
(
l
e
n
+
1
)
=\frac{\sum max+\sum min}{len*(len+1)}
=len∗(len+1)∑max+∑min
这样我们只需要求出所有子区间的最大值和所有子区间的最小值之和就可以了。
对于这类问题,我在这篇文章中详细解释过(双倍经验 )点这里
接下来就是套个板子的事情。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int ul;
typedef pair<ll, ll> PII;
const ll inf = 1e18;
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const ll mod = 1e9 + 7;
const double eps = 1e-8;
#define lowbit(i) (i & -i)
#define Debug(x) cout << (x) << endl
#define fi first
#define se second
#define mem memset
#define endl '\n'
namespace StandardIO {
template<typename T>
inline void read(T &x) {
x = 0; T f = 1;
char c = getchar();
for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
for (; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template<typename T>
inline void write(T x) {
if (x < 0) putchar('-'), x *= -1;
if (x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
}
namespace Comb {
ll f[N];
ll ksm(ll a, ll b) {
ll res = 1, base = a;
while (b) {
if (b & 1) res = res * base % mod;
base = base * base % mod;
b >>= 1;
}
return res;
}
void init() {
f[0] = 1;
for (ll i = 1; i < N; i++) f[i] = f[i - 1] * i % mod;
}
ll C(ll a, ll b) {
if (a < 0 || b < 0 || b > a) return 0;
return f[a] * ksm(f[a - b], mod - 2) % mod * ksm(f[b], mod - 2) % mod;
}
}
namespace ST {
int mi[N][21], ma[N][21], lg[N], a[N];
int cmp1(int x, int y) {
return a[x] < a[y] ? x : y;
}
int cmp2(int x, int y) {
return a[x] > a[y] ? x : y;
}
void init(int n) {
for (int i = 1; i <= n; i++) {
cin >> a[i];
ma[i][0] = mi[i][0] = i, lg[i] = log2(i);
}
for (int i = 1; i <= 20; i++) {
for (int j = 1; j + (1 << i) - 1 <= n; j++) {
mi[j][i] = cmp1(mi[j][i - 1], mi[j + (1 << (i - 1))][i - 1]);
ma[j][i] = cmp2(ma[j][i - 1], ma[j + (1 << (i - 1))][i - 1]);
}
}
}
int qry_mi(int l, int r) {
int k = lg[r - l + 1];
return a[cmp1(mi[l][k], mi[r - (1 << k) + 1][k])];
}
int qry_ma(int l, int r) {
int k = lg[r - l + 1];
return a[cmp2(ma[l][k], ma[r - (1 << k) + 1][k])];
}
int qry_pmi(int l, int r) {
int k = lg[r - l + 1];
return cmp1(mi[l][k], mi[r - (1 << k) + 1][k]);
}
int qry_pma(int l, int r) {
int k = lg[r - l + 1];
return cmp2(ma[l][k], ma[r - (1 << k) + 1][k]);
}
}
using namespace ST;
using namespace Comb;
int n, m, pos[N], lmi[N], rmi[N], lma[N], rma[N], stk[N], tp;
ll f1[N], f2[N], f3[N], f4[N], ans[N], res;
struct Query {
int id, l, r;
}q[N];
bool cmp(Query x, Query y) {
if (pos[x.l] == pos[y.l]) return x.r < y.r;
else return pos[x.l] < pos[y.l];
}
void add_right(int L, int R) {
int p1 = qry_pmi(L, R);
int p2 = qry_pma(L, R);
res += 1ll*(p1 - L + 1) * a[p1] % mod + f1[R] - f1[p1];
res = (res % mod + mod) % mod;
res += 1ll*(p2 - L + 1) * a[p2] % mod + f3[R] - f3[p2];
res = (res % mod + mod) % mod;
}
void add_left(int L, int R) {
int p1 = qry_pmi(L, R);
int p2 = qry_pma(L, R);
res += 1ll*(R - p1 + 1) * a[p1] % mod + f2[L] - f2[p1];
res = (res % mod + mod) % mod;
res += 1ll*(R - p2 + 1) * a[p2] % mod + f4[L] - f4[p2];
res = (res % mod + mod) % mod;
}
void sub_right(int L, int R) {
int p1 = qry_pmi(L, R);
int p2 = qry_pma(L, R);
res -= 1ll*(p1 - L + 1) * a[p1] % mod + f1[R] - f1[p1];
res = (res % mod + mod) % mod;
res -= 1ll*(p2 - L + 1) * a[p2] % mod + f3[R] - f3[p2];
res = (res % mod + mod) % mod;
}
void sub_left(int L, int R) {
int p1 = qry_pmi(L, R);
int p2 = qry_pma(L, R);
res -= 1ll*(R - p1 + 1) * a[p1] % mod + f2[L] - f2[p1];
res = (res % mod + mod) % mod;
res -= 1ll*(R - p2 + 1) * a[p2] % mod + f4[L] - f4[p2];
res = (res % mod + mod) % mod;
}
inline void solve() {
int T; cin >> T; while (T--) {
cin >> n >> m;
init(n);
int siz = sqrt(n);
for (int i = 1; i <= n; i++) pos[i] = i / siz;
for (int i = 1; i <= m; i++) {
cin >> q[i].l >> q[i].r;
q[i].id = i;
}
sort(q + 1, q + m + 1, cmp);
tp = 0;
for (int i = 1; i <= n; i++) {//left samll
while (tp && a[stk[tp]] > a[i]) tp--;
if (!tp) lmi[i] = 0;
else lmi[i] = stk[tp];
stk[++tp] = i;
}
tp = 0;
for (int i = n; i >= 1; i--) {//right small
while (tp && a[stk[tp]] > a[i]) tp--;
if (!tp) rmi[i] = n + 1;
else rmi[i] = stk[tp];
stk[++tp] = i;
}
tp = 0;
for (int i = 1; i <= n; i++) {//left big
while (tp && a[stk[tp]] < a[i]) tp--;
if (!tp) lma[i] = 0;
else lma[i] = stk[tp];
stk[++tp] = i;
}
tp = 0;
for (int i = n; i >= 1; i--) {//right big
while (tp && a[stk[tp]] < a[i]) tp--;
if (!tp) rma[i] = n + 1;
else rma[i] = stk[tp];
stk[++tp] = i;
}
for (int i = 1; i <= n; i++) f1[i] = (f1[lmi[i]] + 1ll * (i - lmi[i]) * a[i] % mod) % mod;
for (int i = n; i >= 1; i--) f2[i] = (f2[rmi[i]] + 1ll * (rmi[i] - i) * a[i] % mod) % mod;
for (int i = 1; i <= n; i++) f3[i] = (f3[lma[i]] + 1ll * (i - lma[i]) * a[i] % mod) % mod;
for (int i = n; i >= 1; i--) f4[i] = (f4[rma[i]] + 1ll * (rma[i] - i) * a[i] % mod) % mod;
int L = 1, R = 0;
res = 0;
for (int i = 1; i <= m; i++) {
while (q[i].l < L) add_left(--L, R);
while (q[i].r > R) add_right(L, ++R);
while (q[i].l > L) sub_left(L++, R);
while (q[i].r < R) sub_right(L, R--);
int len = R - L + 1;
ans[q[i].id] = res * ksm(1ll*len*(len+1) % mod, mod-2) % mod;
}
for (int i = 1; i <= m; i++) printf("%lld\n", (ans[i] + mod) % mod);
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
signed test_index_for_debug = 1;
char acm_local_for_debug = 0;
do {
if (acm_local_for_debug == '$') exit(0);
if (test_index_for_debug > 20)
throw runtime_error("Check the stdin!!!");
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
solve();
#endif
return 0;
}