QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#339520#7901. Basic Substring StructuregoodierTL 2ms26196kbC++144.3kb2024-02-27 15:04:562024-02-27 15:04:56

Judging History

你现在查看的是最新测评结果

  • [2024-02-27 15:04:56]
  • 评测
  • 测评结果:TL
  • 用时:2ms
  • 内存:26196kb
  • [2024-02-27 15:04:56]
  • 提交

answer

#include <bits/stdc++.h>

#define x first
#define y second
#define mp make_pair

using namespace std;
const int N = 2e5 + 10, INF = 1e8;
typedef long long ll;
typedef pair<int,ll> PIL;

ll s1[N], s2[N], ans;
int s[N], slen[N], s3[N], s4[N], c[N], x[N], y[N], sa[N], rk[N], height[N], f[N][19], len[N], n;
map <int, ll> mp1[N];

void get_sa()
{
    int m = n;
    for(int i = 1; i <= m; i++) c[i] = 0;
    for(int i = 1; i <= n; i++) c[x[i] = s[i]]++;
    for(int i = 1; i <= m; i++) c[i] += c[i - 1];;
    for(int i = n; i; i--) sa[c[x[i]]--] = i;

    for(int k = 1; k <= n; k <<= 1)
    {
        int num = 0;
        for(int i = n - k + 1; i <= n; i++) y[++num] = i;
        for(int i = 1; i <= n; i++)
        {
            if(sa[i] > k)
            {
                y[++num] = sa[i] - k;
            }
        }

        for(int i = 1; i <= m; i++) c[i] = 0;
        for(int i = 1; i <= n; i++) c[x[i]]++;
        for(int i = 1; i <= m; i++) c[i] += c[i - 1];
        for(int i = n; i; i--) sa[c[x[y[i]]]--] = y[i], y[i] = 0;

        swap(x, y); m = 0;
        for(int i = 1; i <= n; i++)
        {
            x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? m : ++m;
        }
        if(m == n) break;
    }
}

void get_height()
{
    for(int i = 1; i <= n; i++) rk[sa[i]] = i;
    for(int i = 1, k = 0; i <= n; i++)
    {
        if(rk[i] == 1) continue;
        if(k) k--;
        int j = sa[rk[i] - 1];
        while(i + k <= n && j + k <= n && s[i + k] == s[j + k]) k++;
        height[rk[i]] = k;
    }
}

void init()
{
    for(int i = 2; i <= n; i++) len[i] = len[i >> 1] + 1;
    for(int i = 1; i <= n; i++) f[i][0] = height[i];
    for(int j = 1; j <= len[n]; j++)
    {
        for(int i = 1; i + (1 << j) - 1 <= n; i++)
        {
            f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
        }
    }
}

int querymn(int l, int r)
{
    if(l > r) return INF;
    int t = len[r - l + 1];
    return min(f[l][t], f[r - (1 << t) + 1][t]);
}

int lcp(int i, int j)
{
    if(i == j) return n - i + 1;
    if(i > n || j > n) return 0;
    if(rk[i] > rk[j]) swap(i, j);
    return querymn(rk[i] + 1, rk[j]);
}

int getlcp(int i, int j, int x, int y)
{
    if(i > n || j > n) return 0;
    if(i == j) return n - i + 1;
    int len = lcp(i, j);
    if(i + len - 1 >= x - 1)
    {
        len = x - i;
        if(y == s[j + len])
        {
            len++;
            len += lcp(i + len, j + len);
        }
    }
    return len;
}

void add(int x, int y)
{
    x++;
    for(; x <= n + 1; x += x & -x) c[x] += y;
}

int ask(int x)
{
    x++;
    int res = 0;
    for(; x; x -= x & -x) res += c[x];
    return res;
}

int main()
{
    //freopen("data.in", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        ans = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &s[i]);
            s1[i] = s2[i] = s3[i] = s4[i] = 0;
            mp1[i].clear();
        }
        get_sa(), get_height(), init();
        memset(c, 0, sizeof(c));
        for(int j = 2; j <= n; j++)
        {
            slen[j] = lcp(1, j);
            int l1 = 1, r1 = slen[j], l2 = j, r2 = j + slen[j] - 1;
            s2[l2] += j, s2[r2 + 1] -= j; s3[l2]++, s3[r2 + 1]--;
            if(r1 >= l2)
            {
                s1[r2 + 1] += slen[j];
            }
            else
            {
                s1[r1 + 1] += slen[j], s1[l2] -= slen[j], s1[r2 + 1] += slen[j];
            }
            add(slen[j], 1);
            mp1[r1 + 1][s[r2 + 1]] = mp1[r1 + 1][s[r2 + 1]] + 1 + lcp(r1 + 2, r2 + 2);
            mp1[r2 + 1][s[r1 + 1]] = mp1[r2 + 1][s[r1 + 1]] + 1 + getlcp(r1 + 2, r2 + 2, r2 + 1, s[r1 + 1]);
        }

        ll sum1 = 0, sum3 = 0; int sum2 = 0;
        for(int i = 1; i <= n; i++)
        {
            add(slen[i], -1);
            sum1 += s2[i], sum2 += s3[i], sum3 += s1[i];
            ll ans1 = 0, ans2 = 0;
            ans1 = (ll)(ask(n) - ask(i - 1)) * (i - 1) + (ll)i * sum2 - sum1 + n + sum3;
            for(auto it = mp1[i].begin(); it != mp1[i].end(); it++)
            {
                ans2 = max(ans2, (*it).y);
            }
            ans = ans + ((ans1 + ans2) ^ i);
        }
        printf("%lld\n", ans);
    }
    return 0;
}

详细

Test #1:

score: 100
Accepted
time: 2ms
memory: 26196kb

input:

2
4
2 1 1 2
12
1 1 4 5 1 4 1 9 1 9 8 10

output:

15
217

result:

ok 2 lines

Test #2:

score: -100
Time Limit Exceeded

input:

10000
8
2 1 2 1 1 1 2 2
9
2 2 1 2 1 2 1 2 1
15
2 1 2 1 1 1 1 2 2 1 2 1 2 2 1
2
1 1
10
2 1 1 1 2 2 1 1 2 2
3
2 1 2
11
1 2 2 1 1 2 1 2 2 1 1
14
2 1 1 1 1 2 1 1 1 2 2 1 2 1
12
2 2 2 1 2 2 2 1 1 2 1 2
4
2 1 1 2
8
1 2 2 2 1 2 1 1
8
1 1 2 1 2 1 1 1
6
2 1 1 1 2 2
14
2 2 1 1 1 1 2 2 2 1 2 2 1 1
10
1 2 2 1 1...

output:

100
133
352
4
208
9
259
363
287
16
92
110
58
348
225
3
344
362
374
316
4
17
128
71
15
98
60
260
16
64
28
95
89
105
250
196
20
47
317
63
101
20
24
65
314
362
264
307
359
281
328
295
232
312
3
330
57
328
3
68
35
146
323
45
356
95
245
4
162
356
246
20
151
4
419
393
387
81
269
369
20
58
20
272
3
26
351
...

result: