2019 ICPC Nanjing Regional F. Paper Grading (partición secuencial DFS del árbol del diccionario + árbol de anidación del árbol)

Título:

Tener nnn cadenass 1, s 2 ... sn s_1, s_2 ... s_ns1,s2. . . snQqq operaciones:
1 Q k l r 1 \ Q \ k \ l \ r1 Q k l r     , da la cadenaQQQ , 求sl, sl + 1. . . sr s_l, s_ {l + 1} ... s_rsl,sl + 1. . . srCadena de neutralización QQLa longitud del prefijo común Q es mayor o igual quekk¿Cuántas cadenas hay en k ?
2 a b 2 \ a \ b2 a b   , intercambiasa y sb s_a y s_bsunaY sb
Rango de datos: 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

Ideas de resolución de problemas:

Primero para todo sss construye un árbol de diccionario, cadasss tiene un número de nodo correspondiente, establezcaQQQ 's exkkEl número correspondiente en el árbol del diccionario para una cadena compuesta por letras de k esxxx , luego yQQEl prefijo común Q es mayor o igual quekkEl nodo correspondiente a la cadena de k debe estar enxxx es la raíz del subárbol. Después de procesar el árbol del diccionario en orden DFS, se convierte en un problema de consulta de intervalo. El problema se convierte en un único punto de modificación, encuentre[l, r] [l, r][ l ,r ] el valor interno está en[L, R] [L, R][ L ,¿Cuántos números hay entre R ] ? ¿Esto le resulta familiar al problema? (
Este tipo de problema se puede resolver con CDQ divide and conquistar o tree nest tree. Aquí, se utiliza un árbol de segmento de línea anidado de matriz de árbol.

#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();
}

Supongo que te gusta

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