Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<bits/stdc++.h>
- #define all(x) begin(x),end(x)
- #define make_unique(x) sort(all(x)); x.erase(unique(all(x)), end(x))
- using namespace std;
- using ll = long long;
- void InitIO(string filename = "") {
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- if (filename.size()) {
- freopen((filename + ".in").c_str(), "r", stdin);
- freopen((filename + ".out").c_str(), "w", stdin);
- }
- }
- struct SuffixArray {
- const vector<int> s;
- const int n;
- vector<int> arr;
- vector<int> lcp;
- #define modulo(x) (x >= n ? x - n : x)
- SuffixArray(const vector<int>& str)
- : s(str)
- , n(size(s))
- , arr(n)
- , lcp(n - 1)
- {
- vector<int> c(n), buff(n), ind(n), cnt(n);
- iota(all(arr), 0);
- stable_sort(all(arr), [&] (int i, int j) {
- return s[i] < s[j];
- });
- c[arr[0]] = 0;
- for (int i = 1; i < n; i++) {
- c[arr[i]] = c[arr[i - 1]];
- if (s[arr[i]] != s[arr[i - 1]]) {
- c[arr[i]]++;
- }
- }
- for (int deg = 1; (1 << (deg - 1)) < n; deg++) {
- const int len = 1 << (deg - 1);
- fill(all(cnt), 0);
- ind[0] = 0;
- for (int i = 0; i < n; i++) { arr[i] = modulo(arr[i] - len + n); }
- for (int i = 0; i < n; i++) { cnt[c[arr[i]]]++; }
- for (int i = 1; i < n; i++) { ind[i] = ind[i - 1] + cnt[i - 1]; }
- for (int i = 0; i < n; i++) { buff[ind[c[arr[i]]]++] = arr[i]; }
- copy(all(buff), begin(arr));
- buff[arr[0]] = 0;
- for (int i = 1; i < n; i++) {
- buff[arr[i]] = buff[arr[i - 1]];
- if (c[arr[i]] != c[arr[i - 1]] || c[modulo(arr[i] + len)] != c[modulo(arr[i - 1] + len)]) {
- buff[arr[i]]++;
- }
- }
- copy(all(buff), begin(c));
- }
- vector<int> pos(n);
- for (int i = 0; i < n; i++) {
- pos[arr[i]] = i;
- }
- int pre = 0;
- for (int i = 0; i < n - 1; i++) {
- int p = pos[i];
- int len = min(n - 1 - i, n - 1 - arr[p - 1]);
- int k = max(0, pre - 1);
- lcp[p - 1] = k;
- while (k < len && s[i + k] == s[arr[p - 1] + k]) { lcp[p - 1] = ++k; }
- pre = k;
- }
- }
- #undef modulo
- };
- template<typename T>
- class TSparseTable {
- private:
- int n, p;
- vector<vector<T>> table;
- vector<int> lg2;
- public:
- void Operation(T& ans, T& left, T& right) {
- ans = max(left, right);
- }
- TSparseTable(const vector<T>& arr)
- : n(arr.size())
- , p(log2(n + 1) + 1)
- , table(p, vector<T>(n, 0))
- {
- table[0] = arr;
- for (int d = 1; d < p; d++) {
- int dlt = 1 << (d - 1);
- for (int i = 0; i + dlt < n; i++) {
- Operation(table[d][i], table[d - 1][i], table[d - 1][i + dlt]);
- }
- }
- lg2.resize(n + 1);
- lg2[0] = -1;
- for (int i = 1; i <= n; i++) {
- lg2[i] = lg2[i >> 1] + 1;
- }
- }
- T operator () (int l, int r) {
- if (l > r) return 0;
- int p = lg2[r - l + 1];
- static T answer;
- Operation(answer, table[p][l], table[p][r - (1 << p) + 1]);
- return answer;
- }
- };
- unordered_map<int, ll> cache;
- ll rec(int l, int r, TSparseTable<int>& table, vector<int>& arr) {
- if (l > r) return 0;
- if (cache.count(l)) return cache[l];
- int left = l;
- int right = r;
- int mid;
- int cur = l;
- while (left <= right) {
- mid = (left + right) >> 1;
- if (table(l, mid) == arr[l]) {
- cur = mid;
- left = mid + 1;
- } else {
- right = mid - 1;
- }
- }
- ll res = (cur - l + 1) * 1ll * arr[l] + rec(cur + 1, r, table, arr);
- return cache[l] = res;
- }
- void solve() {
- int n;
- cin >> n;
- vector<int> arr(n);
- cache = unordered_map<int, ll>();
- for (int i = 0; i < n; i++) {
- cin >> arr[i];
- }
- arr.push_back(0);
- SuffixArray suffixArray(arr);
- TSparseTable<int> table(arr);
- ll answer = 0;
- auto get = [&] (int from, int l, int r) {
- //cout << from << ' ' << l << ' ' << r << '\n';
- if (l > r) return 0ll;
- ll value = table(from, l);
- int left = l;
- int right = r;
- int mid;
- int cur = l;
- while (left <= right) {
- mid = (left + right) >> 1;
- if (table(from, mid) == value) {
- cur = mid;
- left = mid + 1;
- } else {
- right = mid - 1;
- }
- }
- return (cur - l + 1) * 1ll * value + rec(cur + 1, n - 1, table, arr);
- };
- for (int i = 1; i <= n; i++) {
- int index = suffixArray.arr[i];
- //cout << "lcp " << suffixArray.lcp[index] << '\n';
- answer += get(index, index + (index < n ? suffixArray.lcp[i - 1] : 0), n - 1);
- //cout << answer << '\n';
- }
- cout << answer << '\n';
- }
- int main() {
- InitIO();
- int t;
- cin >> t;
- while (t--) {
- solve();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement