HAOI2017 供给侧改革
Posted hfccccccccccccc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HAOI2017 供给侧改革相关的知识,希望对你有一定的参考价值。
https://www.luogu.org/problemnew/show/P3732
题目大意
给一个随机生成的 01 串,定义 (f(i,r)) 表示以 ([i,r]) 为起点的后缀中,最长公共前缀最长的两个后缀的最长公共前缀长度。
每次给定 ([l,r]),询问 (sum_{i=l}^{r} f(i,r))。
题解
数据随机,询问的最长公共前缀的长度大概是 50。
离线一下,把询问按照右端点升序排序,然后按从左到右的顺序向 Trie 树插入后缀,顺便记录每个匹配长度对应的最右左端点(这样一定最优),然后在插入后统一处理这个右端点的询问。
复杂度 (O(50N))?
实现
#include <bits/stdc++.h>
using namespace std;
struct Q {
int l, r, id;
Q() {}
Q(int l, int r, int id) : l(l), r(r), id(id) {}
bool operator < (const Q &rhs) const { return r < rhs.r; }
};
const int NN = 100010;
int n, q;
int sz = 1;
Q qlist[NN];
string str;
int nx[NN*55][2], prv[NN*55], ma[55];
int res[NN];
void add(const string &s, int it) {
int t = 0;
for (int i = 0; i < int(s.size()); i++) {
int d = s[i] - ‘0‘;
if (nx[t][d] == -1) nx[t][d] = sz++;
t = nx[t][d];
if (prv[t] >= 0) {
ma[i+1] = max(ma[i+1], prv[t]);
}
prv[t] = it;
}
}
int solve(int l) {
int sm = 0;
for (int i = 50; i >= 1; i--) {
sm += max(0, ma[i] - l + 1) * i;
l = max(l, ma[i] + 1);
}
return sm;
}
int main() {
cin.tie(0);
ios::sync_with_stdio(false);
cin >> n >> q;
cin >> str;
for (int i = 0; i < q; i++) {
int l, r;
cin >> l >> r; l--; r--;
qlist[i] = Q(l, r, i);
}
sort(qlist, qlist + q);
memset(nx, -1, sizeof(nx));
memset(prv, -1, sizeof(prv));
memset(ma, -1, sizeof(ma));
int pq = 0;
for (int i = 0; i < n; i++) {
int l = min(50, n - i);
add(str.substr(i, l), i);
while (pq < q && qlist[pq].r == i) {
res[qlist[pq].id] = solve(qlist[pq].l);
pq++;
}
}
for (int i = 0; i < q; i++) {
cout << res[i] << ‘
‘;
}
return 0;
}
以上是关于HAOI2017 供给侧改革的主要内容,如果未能解决你的问题,请参考以下文章