2019牛客多校第三场883G

求$\sum_{i=l}^ra[i] \geq2\sum_{i=l}^rMax(a[i])$

一样套路。

考虑$l\in[L[i],i]$,满足条件最小的$r$,$sum[r]-sum[l-1]\geq 2a[i]$,$sum[r]\geq 2a[i]+sum[l-1]$,$lower_bound$。

考虑$r\in[i,L[i]]$,满足条件最小的$l$,$sum[r]-sum[l-1]\geq 2a[i]$,$sum[r]-2a[i]\geq sum[l-1]$,$upper_bound$。

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

#include <bits/stdc++.h>
#include <set>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
#define mk make_pair
const int N = 3e5 + 10;
const int mod = 1e9 + 7;
int read()
{
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + c - '0', c = getchar();
return x * f;
}

int L[N], R[N];
int a[N];
ll sum[N];
ll fsum[N];
int main()
{
int T = read();
while (T--)
{
int n = read();

for (int i = 1; i <= n; i++)
a[i] = read(), sum[i] = sum[i - 1] + a[i];
stack<int> s;
a[0] = 1e9;
a[n + 1] = 1e9;
s.push(0);
for (int i = 1; i <= n; i++)
{
while (!s.empty() && a[i] >= a[s.top()])
s.pop();
L[i] = s.top() + 1;
s.push(i);
}
while (!s.empty())
s.pop();
s.push(n + 1);
for (int i = n; i >= 1; i--)
{
while (!s.empty() && a[i] > a[s.top()])
s.pop();
R[i] = s.top() - 1;
s.push(i);
}

ll ans = 0;
for (int i = 1; i <= n; i++)
{
//cout << L[i] << "--" << R[i] << endl;
if (i - L[i] < R[i] - i)
{
for (int j = L[i]; j <= i; j++)
{
ll p = sum[j - 1] + 2ll * a[i];
int r = lower_bound(i + sum, 1 + R[i] + sum, p) - sum;

ans += max(0, R[i] - r + 1);
}
}
//cout << ans << endl;
else
{
for (int j = i; j <= R[i]; j++)
{
ll p = -2ll * a[i] + sum[j];
int l = upper_bound(L[i] + sum - 1, 1 + i + sum - 1, p) - sum - 1;
l += 1;
l = min(l, i);
//cout << j << " " << l << endl;
ans += max(0, l - L[i] + 1);
}
}
}
printf("%lld\n", ans);
}
}