2020-2021 ACM-ICPC, Asia Seoul Regional Contest I Stock Analysis

题目描述

http://codeforces.com/gym/102920/problem/I

Solution

我们考虑使用二维树状数组,但是注意到好像树状数组无法处理矩阵查询最值

但是我们注意到这道题并不需要查询矩阵

实际上我们只需要保证 $x\le l,r\le y$ 即可

注意到这个东西是一个前后缀查询,虽然这样我们可能会查询到 $l>r$ 的点

但实际上我们在加点的时候都保证了 $l\le r$ 所以并不会造成影响

所以我们将区间和和查询一起排序处理即可

时间复杂度 $O(m\log ^2n)$

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
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
#define maxn 2010
#define maxm 200010
#define lowbit(i) ((i) & (-i))
#define ll long long
#define INF 1000000000000000000ll
using namespace std;

int n, m;

ll s[maxn];

struct Query {
int l, r, id; ll v;

friend bool operator < (const Query &u, const Query &v) { return u.v < v.v; }
} Q[maxm], A[maxn * maxn]; int cnt;

ll Bit[maxn][maxn];
void add(int x, int y, ll v) {
for (int i = x; i; i -= lowbit(i))
for (int j = y; j <= n; j += lowbit(j)) Bit[i][j] = max(Bit[i][j], v);
}

ll query(int x, int y) {
ll s = -INF;
for (int i = x; i <= n; i += lowbit(i))
for (int j = y; j; j -= lowbit(j))
s = max(s, Bit[i][j]);
return s;
}

ll ans[maxm];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);

cin >> n >> m;
fill(Bit[0], Bit[0] + maxn * maxn, -INF);
fill(ans, ans + maxm, -INF);
for (int i = 1, x; i <= n; ++i) cin >> x, s[i] = s[i - 1] + x;
for (int i = 1; i <= m; ++i) cin >> Q[i].l >> Q[i].r >> Q[i].v, Q[i].id = i;
sort(Q + 1, Q + m + 1);
for (int i = 1; i <= n; ++i)
for (int j = 0; j < i; ++j) A[++cnt] = { j + 1, i, 0, s[i] - s[j] };
sort(A + 1, A + cnt + 1);
for (int i = 1, j = 0; i <= m; ++i) {
while (j < cnt && A[j + 1].v <= Q[i].v) ++j, add(A[j].l, A[j].r, A[j].v);
ans[Q[i].id] = max(ans[Q[i].id], query(Q[i].l, Q[i].r));
}
for (int i = 1; i <= m; ++i)
if (ans[i] == -INF) cout << "NONE\n";
else cout << ans[i] << "\n";
return 0;
}