TernaryTree @ 2023-07-01 14:41:40
前缀最大值个数期望是
#include <bits/stdc++.h>
using namespace std;
namespace GenHelper
{
unsigned z1,z2,z3,z4,b;
unsigned rand_()
{
b=((z1<<6)^z1)>>13;
z1=((z1&4294967294U)<<18)^b;
b=((z2<<2)^z2)>>27;
z2=((z2&4294967288U)<<2)^b;
b=((z3<<13)^z3)>>21;
z3=((z3&4294967280U)<<7)^b;
b=((z4<<3)^z4)>>12;
z4=((z4&4294967168U)<<13)^b;
return (z1^z2^z3^z4);
}
}
void srand(unsigned x)
{using namespace GenHelper;
z1=x; z2=(~x)^0x233333333U; z3=x^0x1234598766U; z4=(~x)+51;}
int read()
{
using namespace GenHelper;
int a=rand_()&32767;
int b=rand_()&32767;
return a*32768+b;
}
const int maxn = 2e7 + 10;
typedef unsigned long long ull;
int a[maxn];
int lst[maxn], ltop;
int rst[maxn], rtop;
int lm[maxn], rm[maxn];
signed main() {
ull tot = 0;
int n, q, s;
cin >> n >> q >> s;
srand(s);
for (int i = 1; i <= n; ++i) {
a[i] = read();
}
for (int i = 1; i <= n; ++i) {
while (ltop && a[lst[ltop]] <= a[i]) --ltop;
lm[i] = !ltop ? 0 : lst[ltop];
lst[++ltop] = i;
}
for (int i = n; i >= 1; --i) {
while (!rtop && a[rst[rtop]] <= a[i]) --rtop;
rm[i] = !rtop ? n + 1 : rst[rtop];
rst[++rtop] = i;
}
while (q--) {
int l, r, p, q;
l = read() % n + 1;
r = read() % n + 1;
if (l > r) swap(l, r);
p = l, q = r;
int ans = 0;
while (p <= r && q >= l && p <= q) {
ans = max(ans, max(a[p], a[q]));
p = rm[p], q = lm[q];
}
tot += (ull) ans;
}
cout << tot << endl;
return 0;
}
by Querainy @ 2023-07-01 14:42:53
你可以在单调栈上二分的。
by TernaryTree @ 2023-07-01 14:44:41
@华山抡剑 没学过,有无博客/kel
by Querainy @ 2023-07-01 14:57:33
@TernaryTree ?你离线下来,单调栈跑到右端点的时候直接二分找左端点右边第一个
by TernaryTree @ 2023-07-01 15:00:46
@华山抡剑 不是很懂,我手玩一下