Skip to content

Commit d1be20e

Browse files
committed
LibreOJ: 2133
「NOI2015」品酒大会
1 parent d448bfb commit d1be20e

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

LibreOJ/2133.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* @file 2133.cpp
3+
* @author Macesuted ([email protected])
4+
* @date 2022-07-04
5+
*
6+
* @copyright Copyright (c) 2022
7+
*
8+
*/
9+
10+
#include <bits/stdc++.h>
11+
using namespace std;
12+
13+
#ifndef LOCAL
14+
#define endl '\n'
15+
#endif
16+
17+
bool mem1;
18+
19+
#define maxn 300005
20+
21+
typedef pair<int64_t, int64_t> pll;
22+
23+
int a[maxn], rk[maxn], ork[maxn << 1], buc[maxn], id[maxn], val[maxn], sa[maxn], h[maxn], fa[maxn], siz[maxn];
24+
pll ht[maxn];
25+
multiset<int> maxVal[maxn], minVal[maxn];
26+
27+
int getfa(int p) { return fa[p] == p ? p : fa[p] = getfa(fa[p]); }
28+
29+
void solve(void) {
30+
int n;
31+
string s;
32+
cin >> n >> s;
33+
int m = max(n, 256);
34+
for (int i = 1; i <= n; i++) buc[rk[i] = s[i - 1]]++;
35+
for (int i = 1; i <= m; i++) buc[i] += buc[i - 1];
36+
for (int i = n; i; i--) sa[buc[rk[i]]--] = i;
37+
for (int l = 1; l == 1 || n != m; l <<= 1) {
38+
for (int i = n - l + 1; i <= n; i++) id[i + l - n] = i;
39+
for (int i = 1, j = l; i <= n; i++)
40+
if (sa[i] > l) id[++j] = sa[i] - l;
41+
for (int i = 1; i <= m; i++) buc[i] = 0;
42+
for (int i = 1; i <= n; i++) buc[val[i] = rk[id[i]]]++;
43+
for (int i = 1; i <= m; i++) buc[i] += buc[i - 1];
44+
for (int i = n; i; i--) sa[buc[val[i]]--] = id[i];
45+
for (int i = 1; i <= n; i++) ork[i] = rk[i];
46+
m = 0;
47+
for (int i = 1; i <= n; i++) {
48+
if (ork[sa[i]] != ork[sa[i - 1]] || ork[sa[i] + l] != ork[sa[i - 1] + l]) m++;
49+
rk[sa[i]] = m;
50+
}
51+
}
52+
s.push_back('#');
53+
for (int i = 1; i <= n; i++) {
54+
if (rk[i] == 1) continue;
55+
h[rk[i]] = max(h[rk[i - 1]] - 1, 0);
56+
while (s[sa[rk[i] - 1] + h[rk[i]] - 1] == s[i + h[rk[i]] - 1]) h[rk[i]]++;
57+
}
58+
for (int i = 1; i <= n; i++) cin >> a[rk[i]];
59+
for (int i = 1; i <= n; i++) fa[i] = i, siz[i] = 1, maxVal[i].insert(a[i]), minVal[i].insert(a[i]);
60+
for (int i = 2; i <= n; i++) ht[i] = {h[i], i};
61+
sort(ht + 2, ht + n + 1, greater<pll>());
62+
int64_t ans1 = 0, ans2 = 0;
63+
stack<pll> ans;
64+
for (int i = n - 1, j = 2; ~i; i--) {
65+
while (j <= n && ht[j].first >= i) {
66+
int x = ht[j++].second, f1 = getfa(x - 1), f2 = getfa(x);
67+
if (!ans1)
68+
ans2 = max((int64_t)*maxVal[f1].rbegin() * *maxVal[f2].rbegin(),
69+
(int64_t)*minVal[f1].begin() * *minVal[f2].begin());
70+
ans1 += 1LL * siz[f1] * siz[f2];
71+
ans2 = max({ans2, (int64_t)*maxVal[f1].rbegin() * *maxVal[f2].rbegin(),
72+
(int64_t)*minVal[f1].begin() * *minVal[f2].begin()});
73+
for (auto i : maxVal[f2]) maxVal[f1].insert(i);
74+
for (auto i : minVal[f2]) minVal[f1].insert(i);
75+
maxVal[f2].clear(), minVal[f2].clear();
76+
while (maxVal[f1].size() > 2) maxVal[f1].erase(maxVal[f1].begin());
77+
while (minVal[f1].size() > 2) minVal[f1].erase(--minVal[f1].end());
78+
siz[f1] += siz[f2], fa[f2] = f1;
79+
}
80+
ans.emplace(ans1, ans2);
81+
}
82+
while (!ans.empty()) cout << ans.top().first << ' ' << ans.top().second << endl, ans.pop();
83+
return;
84+
}
85+
86+
bool mem2;
87+
88+
int main() {
89+
ios::sync_with_stdio(false), cin.tie(nullptr);
90+
#ifdef LOCAL
91+
cerr << "Memory Cost: " << abs(&mem1 - &mem2) / 1024. / 1024. << "MB" << endl;
92+
#endif
93+
94+
int _ = 1;
95+
while (_--) solve();
96+
97+
#ifdef LOCAL
98+
cerr << "Time Cost: " << clock() * 1000. / CLOCKS_PER_SEC << "MS" << endl;
99+
#endif
100+
return 0;
101+
}

0 commit comments

Comments
 (0)