【BZOJ 3879】SvT

http://www.lydsy.com/JudgeOnline/problem.php?id=3879

SvT的中文是后缀虚树?

反正本蒟蒻不懂,还是$O(nlogn)$的后缀数组和单调栈维护来做,fye学姐讲了这种学法(当时并没有听懂QwQ),xiaoyimi教会了我这种做法→xiaoyimi的题解

一开始贡献了2次TLE,以为是玄学的死循环,果断挂起对拍器拍了一晚上,然后在回家的路上才想起来TLE是因为提交的时候忘删freopen了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 500003;
const ll p = 23333333333333333ll;
int in() {
    int k = 0, fh = 1; char c = getchar();
    for(; c < ‘0‘ || c > ‘9‘; c = getchar())
        if (c == ‘-‘) fh = -1;
    for(; c >= ‘0‘ && c <= ‘9‘; c = getchar())
        k = (k << 3) + (k << 1) + c - ‘0‘;
    return k * fh;
}

int c[N], t1[N], t2[N];

void st(int *x, int *y, int *sa, int n, int m) {
    for(int i = 0; i < m; ++i) c[i] = 0;
    for(int i = 0; i < n; ++i) ++c[x[y[i]]];
    for(int i = 1; i < m; ++i) c[i] += c[i - 1];
    for(int i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i];
}

void mkhz(int *r, int *sa, int n, int m) {
    int *x = t1, *y = t2, *t, p, i, j;
    for(i = 0; i < n; ++i) x[i] = r[i], y[i] = i;
    st(x, y, sa, n, m);
    for(p = 1, j = 1; p < n; m = p, j <<= 1) {
        for(p = 0, i = n - j; i < n; ++i) y[p++] = i;
        for(i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
        st(x, y, sa, n, m);
        for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; ++i)
            x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + j] == y[sa[i - 1] + j] ? p - 1 : p++;
    }
}

void mkh(int *r, int *sa, int *rank, int *h, int n) {
    int k = 0, j, i;
    for(i = 0; i < n; ++i) rank[sa[i]] = i;
    for(i = 1; i < n; h[rank[i++]] = k)
        for(k ? --k : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; ++k);
}

char s[N];
int n, m, sa[N], rank[N], r[N], h[N], f[N][20], Log_2[N], a[N];

int get_min(int l, int r) {
    int len = Log_2[r - l];
    return min(f[l][len], f[r - (1 << len)][len]);
}

int get_LCP(int l, int r) {
    l = rank[l]; r = rank[r];
    if (l > r) swap(l, r);
    return get_min(l, r);
}

bool cmp(int x, int y) {
    return rank[x] < rank[y];
}

int sta[N], top, bef[N], size[N];

void sub(ll &x, ll y) {
    x -= y; if (x < 0) x += p;
}

void add(ll &x, ll y) {
    x += y; if (x > p) x -= p;
}

int main() {
    n = in(); m = in();
    scanf("%s", s + 1);
    r[0] = 0;
    for(int i = 1; i <= n; ++i) r[i] = s[i] - ‘a‘ + 1;
    mkhz(r, sa, n + 1, 27);
    mkh(r, sa, rank, h, n + 1);

    for(int i = 0; i < n; ++i) f[i][0] = h[i + 1];
    for(int j = 1; j < 20; ++j)
        for(int i = 0; i < n; ++i) {
            if (i + (1 << (j - 1)) >= n) break;
            f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
        }

    int tmp = 0;
    for(int i = 1; i <= n; ++i) {
        if ((1 << (tmp + 1)) < i) ++tmp;
        Log_2[i] = tmp;
    }

    int tot; ll sum, ans = 0;
    while (m--) {
        tot = in();
        for(int i = 1; i <= tot; ++i) a[i] = in();
        sort(a + 1, a + tot + 1, cmp);
        tot = unique(a + 1, a + tot + 1) - a;
        --tot;
        for(int i = 1; i < tot; ++i) bef[i] = get_LCP(a[i], a[i + 1]);

        top = 0; sum = 0; ans = 0;
        for(int i = 1; i < tot; ++i) {
            size[i] = 1;
            while (top && bef[i] < bef[sta[top]]) {
                sub(sum, 1ll * bef[sta[top]] * size[sta[top]] % p);
                size[i] += size[sta[top]];
                --top;
            }
            sta[++top] = i;
            add(sum, 1ll * bef[i] * size[i] % p);
            add(ans, sum);
        }
        printf("%lld\n", ans);
    }

    return 0;
}

再一次被自己的智商感动QAQ

时间: 2024-10-19 19:24:36

【BZOJ 3879】SvT的相关文章

【BZOJ 2820】 YY的GCD

2820: YY的GCD Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 807  Solved: 404 [Submit][Status] Description 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对 kAc这种傻×必然不会了,于是向你来请教-- 多组输入 Input 第一行一个整数T 表述数据组数 接下来T行,每行两个正整数,表示

【BZOJ 1854】 [Scoi2010]游戏

1854: [Scoi2010]游戏 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 2609  Solved: 931 [Submit][Status] Description lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使用一次. 游戏进行到最后,lxhgww遇到了终极boss,这个终极bos

【BZOJ 1036】【ZJOI 2008】树的统计

此题为树链剖分的裸题. 代码如下,使用常用的轻重链剖分. /************************************************************** Problem: 1036 User: Evensgn Language: C++ Result: Accepted Time:2468 ms Memory:5772 kb ****************************************************************/ #inc

【BZOJ 1150】 1150: [CTSC2007]数据备份Backup (贪心+优先队列)

1150: [CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣.已知办公 楼都位于同一条街上.你决定给这些办公楼配对(两个一组).每一对办公楼可以通过在这两个建筑物之间铺设网 络电缆使得它们可以互相备份.然而,网络电缆的费用很高.当地电信公司仅能为你提供 K 条网络电缆,这意味 着你仅

【BZOJ 2823】 [AHOI2012]信号塔

2823: [AHOI2012]信号塔 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 469  Solved: 198 [Submit][Status][Discuss] Description 在野外训练中,为了确保每位参加集训的成员安全,实时的掌握和收集周边环境和队员信息非常重要,集训队采用的方式是在训练所在地散布N个小型传感器来收集并传递信息,这些传感器只与设在集训地中的信号塔进行通信,信号塔接收信号的覆盖范围是圆形,可以接收到所有分布在

【BZOJ 3190】 [JLOI2013]赛车

3190: [JLOI2013]赛车 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 803 Solved: 279 [Submit][Status][Discuss] Description 这里有一辆赛车比赛正在进行,赛场上一共有N辆车,分别称为个g1,g2--gn.赛道是一条无限长的直线.最初,gi位于距离起跑线前进ki的位置.比赛开始后,车辆gi将会以vi单位每秒的恒定速度行驶.在这个比赛过程中,如果一辆赛车曾经处于领跑位置的话(即没有其他

【BZOJ 2115】 [Wc2011] Xor

2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 962  Solved: 441 [Submit][Status] Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边. 图中可能有重边或自环. Output 仅包含一个整数,表示最大的XOR和(十进

【BZOJ 1146】 [CTSC2008]网络管理Network

1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MB Submit: 1938  Solved: 577 [Submit][Status] Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成.每个部门都有一个专属的路由器,部门局域网内的所有机

【BZOJ 2738】 矩阵乘法

2738: 矩阵乘法 Time Limit: 20 Sec Memory Limit: 256 MB Submit: 841 Solved: 351 [Submit][Status][Discuss] Description 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. Input 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N*N个数,表示这个矩阵: 再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角.