LibreOJ #2033. 「SDOI2016」生成魔咒

二次联通门 : LibreOJ #2033. 「SDOI2016」生成魔咒

/*
    LibreOJ #2033. 「SDOI2016」生成魔咒

    调了整整一天啊。。。
    绝望啊

    最后发现是1打成i了啊!!!

*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>

const int BUF = 10000020;
char Buf[BUF], *buf = Buf;

void read (int &now)
{
    for (now = 0; !isdigit (*buf); ++ buf);
    for (; isdigit (*buf); now = now * 10 + *buf - ‘0‘, ++ buf);
}

#define Max 200005

int sa[Max], __rank[Max], height[Max];
int str_1[Max], str_2[Max];
int c[Max];

inline void Swap (int *&x, int *&y)
{
    int *now = x;
    x = y;
    y = now;
}

inline int min (int a, int b)
{
    return a < b ? a : b;
}

void D ()
{
    putchar (‘\n‘);
    for (int i = 1; i <= 10; i ++)
        printf ("%d ", sa[i]);
            putchar (‘\n‘);}
void Build_Sa (int *line, int N, int M)
{
    static int *x = str_1, *y = str_2; register int i, pos;
    for (i = 0; i < M; c[i ++] = 0);
       for (i = 0; i < N; c[x[i] = line[i]] ++, ++ i);
    for (i = 1; i < M; c[i] += c[i - 1], ++ i);
    for (i = N - 1; i >= 0; sa[-- c[x[i]]] = i, i --);
    for (int j = 1; pos < N; j <<= 1, M = pos)
    {
        for (i = N - j, pos = 0; i < N; y[pos ++] = i ++);
        for (i = 0; i < N; ++ i) if (sa[i] >= j) y[pos ++] = sa[i] - j;
        for (i = 0; i < M; c[i ++] = 0);
        for (i = 0; i < N; ++ c[x[y[i]]], ++ i);
        for (i = 0; i < M; c[i] += c[i - 1], ++ i);
        for (i = N - 1; i >= 0; sa[-- c[x[y[i]]]] = y[i --]);
        Swap (x, y), pos = 1, x[sa[0]] = 0;
        for (i = 1; i < N; ++ i)
            x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + j] == y[sa[i - 1] + j] ? pos - 1 : pos ++;
    }
    int j;
    for (i = 1; i < N; __rank[sa[i]] = i, ++ i);
    for (i = 0, pos = 0; i < N - 1; height[__rank[i ++]] = pos)
        for (pos ? pos -- : 0, j = sa[__rank[i] - 1]; line[i + pos] == line[j + pos]; ++ pos);
}

inline int max (int a, int b)
{
    return a > b ? a : b;
}
int number[Max], level[Max];

int st[Max][20];
int Stack[Max], data[Max];

int value[Max];
std :: map<int,int>hash;  

int Main ()
{
    fread (buf, 1, BUF, stdin);
    int N;
    read (N);
    register int i;
    for (i = 0; i < N; ++ i)
        read (number[i]), level[i] = number[i];

    int Size = 0;
    for (i = 0; i < N; ++ i)
        if (hash.find (number[i]) == hash.end ())
            hash[level[i]] = ++ Size;
    for (i = 0; i < N; ++ i)
        level[i] = hash[level[i]];

    Build_Sa (level, N + 1, Size + 1);
    for (i = 1; i <= N; st[i][0] = height[i], ++ i);
    for (int j = 1; j <= 17; ++ j)
        for (i = 1; i + (1 << j - 1) <= N; ++ i)
            st[i][j] = min (st[i][j - 1], st[i + (1 << j - 1)][j - 1]);

    int top = 0, res, pos, l;

    for (i = 1; i <= N; ++ i)
    {
        for (; sa[Stack[top]] > sa[i] && top; -- top);
        res = Stack[top] + 1;
        l = (int) log2 (i - res + 1);

        data[i] = min (st[res][l], st[i - (1 << l) + 1][l]);
        Stack[++ top] = i;
    }
    for (i = N, Stack[top = 0] = N + 1; i; -- i)
    {
        for (; sa[Stack[top]] > sa[i] && top; -- top);
        res = Stack[top];
        l = (int) log2 (res - i);

        data[i] = max (data[i], min (st[i + 1][l], st[res - (1 << l) + 1][l]));
        Stack[++ top] = i;
    }

    for (i = 1; i <= N; ++ i)
        value[data[i] + sa[i]] ++;

    long long now = 0, Answer = 0;
    for (i = 0; i < N; ++ i)
    {
        now += value[i];
        Answer += now;
        printf ("%lld\n", Answer);
    }

    return 0;
}
int ZlycerQan = Main ();
int main (int argc, char *argv[]) {;}
时间: 2024-08-04 15:17:36

LibreOJ #2033. 「SDOI2016」生成魔咒的相关文章

【SDOI2016】生成魔咒

Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例如 S=[1,2,1] 时,它的生成魔咒有 [1].[2].[1,2].[2,1].[1,2,1] 五种.S=[1,1,1] 时,它的生成魔咒有 [1]. [1,1].[1,1,1] 三种.最初 S 为空串.共进行 n 次操作,每次操作是在 S 的结尾加入一个魔咒字符.每次操作后都 需要求出,当前的

cogs 2223. [SDOI2016 Round1] 生成魔咒

★★☆ 输入文件:menci_incantation.in 输出文件:menci_incantation.out 简单对比 时间限制:1 s 内存限制:128 MB [题目描述]魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2].一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒.例如 S=[1,2,1] 时,它的生成魔咒有 [1].[2].[1,2].[2,1].[1,2,1] 五种.S=[1,1,1] 时,它的生成魔咒有 [1

【BZOJ4516】【SDOI2016】生成魔咒 [SAM]

生成魔咒 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例如 S=[1,2,1] 时,它的生成魔咒有 [1].[2].[1,2].[2,1].[1,2,1] 五种. S=[1,1,1] 时,它的生成魔咒有 [1].[

[Sdoi2016]生成魔咒[SAM or SA]

4516: [Sdoi2016]生成魔咒 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1017  Solved: 569[Submit][Status][Discuss] Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例如 S=[1,2,1] 时,它的生成魔咒有 [1].[2].[1,2].[2

BZOJ4516: [Sdoi2016]生成魔咒 后缀自动机

#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> #include<algorithm> #include<cstdlib> #include<map> #define N 200005 #define ll long long using namespace std; int read()

bzoj4516: [Sdoi2016]生成魔咒(SAM)

4516: [Sdoi2016]生成魔咒 题目:传送门 题解: 真奥义之SAM裸题... 其实对于当前新增节点x的操作,每次对ans的贡献就是dep[x]-dep[fail[x]](根据fail指针的定义随便YY) 然后有思路之后乍看题目每个x是10^9...瞬间GG %了已发cc然后被D飞,直接上map啊 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath

P4070 [SDOI2016]生成魔咒

题目地址:P4070 [SDOI2016]生成魔咒 相信看到题目之后很多人跟我的思路是一样的-- 肯定要用 SA(P3809 [模板]后缀排序) 肯定要会求本质不同的子串个数(P2408 不同子串个数) 然后?就不会了...... 瓶颈在哪儿? 你会发现每往后添加一个字符,整个 sa 数组只会插入一个数,要维护不难 但是 height 会无规律变化,这就导致无法高效维护 怎么办呢? 倒置字符串 我们将整个字符串倒置过来 显然本质不同的子串个数不会变化 而每往前添加一个字符串, height 的变

[SDOI2016] 生成魔咒 - 后缀数组,平衡树,STL,时间倒流

[SDOI2016] 生成魔咒 Description 初态串为空,每次在末尾追加一个字符,动态维护本质不同的子串数. Solution 考虑时间倒流,并将串反转,则变为每次从开头删掉一个字符,即每次从后缀集合中删掉一个后缀. 预处理出后缀数组和高度数组后,用平衡树维护所有后缀集合(按照后缀排序),要删除一个后缀 \(S[sa[p],n]\) 时,找到它在平衡树上的前驱 \(u\) 和后继 \(v\) ,如果都存在,那么这一步的贡献就是 \[(n-sa[p]+1) - Max(h[p],h[v]

Bzoj4516 [Sdoi2016]生成魔咒

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 947  Solved: 529 Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例如 S=[1,2,1] 时,它的生成魔咒有 [1].[2].[1,2].[2,1].[1,2,1] 五种.S=[1,1,1] 时,它的生成魔咒有 [1]. [1,1].[