2019 ICPC Nanjing Regional F. Classificação de papel (partição sequencial DFS da árvore de dicionário + árvore de aninhamento de árvore)

Título:

Tem nnn stringss 1, s 2 ... sn s_1, s_2 ... s_ns1,s2. . . snQqoperações q :
1 Q k l r 1 \ Q \ k \ l \ r1 Q k l r     , dá a stringQQQ , 求sl, sl + 1. . . sr s_l, s_ {l + 1} ... s_rsl,sl + 1. . . srSequência de neutralização QQO comprimento do prefixo comum Q é maior ou igual akkQuantas cordas existem em k ?
2 a b 2 \ a \ b2 a b   , troquesa e sb s_a e PacsumE sb
Intervalo de dados: n, q ≤ 2 e 5, ∑ ∣ s ∣ ≤ 2 e 5, ∑ ∣ Q ∣ ≤ 2 e 5, k ≤ ∣ Q ∣ n, q \ le 2e5, \ \ sum | s | \ le 2e5 , \ \ sum | Q | \ le 2e5, k \ le | Q |n ,q2 e 5 , s 2 e 5 , Q 2 e 5 ,kQ

Ideias para resolução de problemas:

Primeiro para todos os sss constrói uma árvore de dicionário, cadasss tem um número de nó correspondente, definaQQKkanterior de QO número correspondente na árvore do dicionário para uma string composta de letras de k éxxx , então eQQO prefixo comum Q é maior ou igual akkO nó correspondente à string de k deve estar emxxx é a raiz da subárvore. Depois de processar a árvore de dicionário na ordem DFS, torna-se um problema de consulta de intervalo. O problema se torna um único ponto de modificação, encontre[l, r] [l, r][ l ,r ] valor interno está em[L, R] [L, R][ L ,Quantos números existem entre R ] ? Isso se torna familiar para o problema? (
Este tipo de problema pode ser resolvido com CDQ dividir e conquistar ou árvore de ninho de árvore, aqui usamos árvore de segmento de linha aninhada de matriz de árvore.

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-(x)))
#define mid ((l+r)>>1)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
const int maxn = 2e5 + 50;
int ch[maxn][26], sz[maxn], idx = 0;
int T[maxn], val[maxn*200], lc[maxn*200], rc[maxn*200], tot;
int n, q;
void update(int &rt, int l, int r, int pos, int x){
    
    
    if(!rt) rt = ++tot;
    val[rt]+=x;
    if(l == r) return;
    if(pos <= mid) update(lc[rt], l, mid, pos, x);
    else update(rc[rt], mid+1, r, pos, x);
    return;
}
int qry(int rt, int l, int r, int L, int R){
    
    
    if(!rt) return 0;
    if(L <= l && r <= R) return val[rt];
    int res = 0;
    if(L <= mid) res += qry(lc[rt], l, mid, L, R);
    if(R > mid) res += qry(rc[rt], mid+1, r, L, R);
    return res;
}
void add(int i, int pos, int x){
    
    
    while(i <= n){
    
    
        update(T[i], 1, idx, pos, x);
        i += lowbit(i);
    }return;
}
int sum(int i, int L, int R){
    
    
    int res = 0;
    while(i){
    
    
        res += qry(T[i], 1, idx, L, R);
        i -= lowbit(i);
    }return res;
}
int root, cnt;
int add(char *s){
    
    
    int p = root;
    while(*s){
    
    
        int x = *s-'a';
        if(!ch[p][x]) ch[p][x] = ++cnt;
        p = ch[p][x];
        s++;
    }return p;
}
int dfn[maxn], id[maxn];
void dfs(int u){
    
    
    dfn[++idx] = u; id[u] = idx;
    sz[u] = 1;
    for(int i = 0; i < 26; ++i){
    
    
        if(ch[u][i]) dfs(ch[u][i]), sz[u] += sz[ch[u][i]];
    }return;
}

char s[maxn];
int to[maxn];
void init(){
    
    
    scanf("%d%d", &n, &q);
    cnt = 0; root = ++cnt;
    for(int i = 1; i <= n; ++i){
    
    
        scanf("%s", s); to[i] = add(s);
        //cout<<"i:"<<i<<" t:"<<to[i]<<endl;
    }
    dfs(root);
    //cout<<"idx:"<<idx<<endl;
    for(int i = 1; i <= n; ++i){
    
    
        add(i, id[to[i]], 1);
    }
}
int get_to(int k){
    
    
    int p = root;
    for(int i = 0; i < k; ++i){
    
    
        int x = s[i]-'a';
        if(!ch[p][x]) return -1;
        p = ch[p][x];
    }return p;
}
void sol(){
    
    
    while(q--){
    
    
        int op; scanf("%d", &op);
        if(op == 1){
    
    
            int u, v; scanf("%d%d", &u, &v);
            add(u, id[to[u]], -1);
            add(u, id[to[v]], 1);
            add(v, id[to[v]], -1);
            add(v, id[to[u]], 1);
            swap(to[u], to[v]);
        }else{
    
    
            int k, l, r, L, R;
            scanf("%s", s);
            scanf("%d%d%d", &k, &l, &r);
            int u = get_to(k);
            if(u == -1){
    
    
                printf("0\n"); continue;
            }
            L = id[u], R = id[u]+sz[u]-1;
            //cout<<"L:"<<L<<" R:"<<R<<endl;
            int ans = sum(r, L, R)-sum(l-1, L, R);
            printf("%d\n", ans);
        }
    }
}
int main()
{
    
    
    init();
    sol();
}

Acho que você gosta

Origin blog.csdn.net/qq_43202683/article/details/104100136
Recomendado
Clasificación