zoukankan      html  css  js  c++  java
  • 2019 ICPC Asia Nanjing Regional F. Paper Grading (字典树DFS序+带修主席树)

    题目链接:https://nanti.jisuanke.com/t/42400

    题意:给一个模式串集合,序号1~n,有T个操作,或者是交换序号,或者是查询模式串集合中序号在L到R之 间的字符串有多少个和目标串公共前缀长度大于等于K。
    —————————————————————————————————
    对模式串集合建字典树,则与目标串(LCP)大于等K的字符串,都在以目标串第(K)个字符所在的结点为根的子树中,每个模式串插入字典树的过程中记录序号,修改时交换序号,询问就相于在子树中询问有多少结点的序号在(L)(R)之间。
    涉及到子树,容易想到建立(DFS)序,再用数据结构维护
    但是不建议在字典树的(DFS)序上用数据结构维护,因为可能出现两个一样的模式串,但是序号不一样,可能会覆盖之前的序号(个人观点,我写的时候是遇到了这种问题,可能写法问题)
    所以可以用一个数组(h[i]),表示序号为(i)的字符串在字典树中的编号为(h[i]),对(h)使用数据结构维护,需要支持单点修改(交换视为两次单点修改)和查询区间([L,R])(h[i])的值在范围([in[x],out[x]])中的数量((x)为目标串第(K)字符在字典树中的结点编号)

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 200010;
    int ptov[maxn], tv[maxn];
    /************************************************************/
    struct Trie
    {
        int trie[maxn][26], tot = 0;
        int ins(char s[])
        {
            int len = strlen(s);
            int root = 0;
            for (int i = 0; i < len; i++)
            {
                int id = s[i] - 'a';
                if (trie[root][id] == 0)
                    trie[root][id] = ++tot;
                root = trie[root][id];
            }
            return root;
        }
        int fin(int k, char s[])
        {
            int root = 0;
            for (int i = 0; i < k; i++)
            {
                int id = s[i] - 'a';
                if (trie[root][id] == 0)
                    return -1;
                root = trie[root][id];
            }
            return root;
        }
    } t;
    /************************************************************/
    int in[maxn], out[maxn];
    int tim = 0;
    void dfs(int x)
    {
        in[x] = ++tim;
        for (int i = 0; i < 26; i++)
        {
            if (t.trie[x][i] == 0)
                continue;
            dfs(t.trie[x][i]);
        }
        out[x] = tim;
    }
    /************************************************************/
    int T[maxn], S[maxn], L[maxn * 150], R[maxn * 150], sum[maxn * 150];
    int h[maxn];
    int ul[maxn], ur[maxn];
    int tot, num, n, m;
    
    struct node
    {
        int l, r, k;
        bool flag;
    } Q[maxn << 1];
    
    void build(int &rt, int l, int r)
    {
        rt = ++tot;
        sum[rt] = 0;
        if (l == r)
            return;
        int mid = (l + r) >> 1;
        build(L[rt], l, mid);
        build(R[rt], mid + 1, r);
    }
    
    void update(int &rt, int pre, int l, int r, int x, int val)
    {
        rt = ++tot;
        L[rt] = L[pre];
        R[rt] = R[pre];
        sum[rt] = sum[pre] + val;
        if (l == r)
            return;
        int mid = (l + r) >> 1;
        if (x <= mid)
            update(L[rt], L[pre], l, mid, x, val);
        else
            update(R[rt], R[pre], mid + 1, r, x, val);
    }
    
    int lowbit(int x) { return x & (-x); }
    
    void add(int x, int val)
    {
        int res = lower_bound(h + 1, h + 1 + num, ptov[x]) - h;
        while (x <= n)
        {
            update(S[x], S[x], 1, num, res, val);
            x += lowbit(x);
        }
    }
    
    int Sum(int x, int flag)
    {
        int res = 0;
        while (x > 0)
        {
            if (flag == 1)
                res += sum[L[ur[x]]];
            else if (flag == 2)
                res += sum[L[ul[x]]];
            else if (flag == 3)
                res += sum[ur[x]];
            else
                res += sum[ul[x]];
            x -= lowbit(x);
        }
        return res;
    }
    int query(int s, int e, int ts, int te, int l, int r, int k)
    {
        if (l == r)
            return Sum(e, 3) - Sum(s, 4) + sum[te] - sum[ts];
        int mid = (l + r) >> 1;
        int res = Sum(e, 1) - Sum(s, 2) + sum[L[te]] - sum[L[ts]];
        if (k <= mid)
        {
            for (int i = e; i; i -= lowbit(i))
                ur[i] = L[ur[i]];
            for (int i = s; i; i -= lowbit(i))
                ul[i] = L[ul[i]];
            return query(s, e, L[ts], L[te], l, mid, k);
        }
        else
        {
            for (int i = e; i; i -= lowbit(i))
                ur[i] = R[ur[i]];
            for (int i = s; i; i -= lowbit(i))
                ul[i] = R[ul[i]];
            return res + query(s, e, R[ts], R[te], mid + 1, r, k);
        }
    }
    /************************************************************/
    char s[maxn];
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
        {
            scanf("%s", s);
            ptov[i] = t.ins(s);
        }
        dfs(0);
        for (int i = 1; i <= n; i++)
        {
            ptov[i] = in[ptov[i]];
            h[i] = ptov[i];
            tv[i] = ptov[i];
        }
        int q = 0;
        for (int i = 1; i <= m; i++)
        {
            int opt;
            scanf("%d", &opt);
            if (opt == 2) //询问
            {
                scanf("%s%d%d%d", s, &Q[q].k, &Q[q].l, &Q[q].r);
                Q[q].k = t.fin(Q[q].k, s);
                Q[q].flag = true;
                q++;
            }
            else //修改
            {
                int tl, tr;
                scanf("%d%d", &tl, &tr);
                Q[q].l = tl;
                Q[q].r = tv[tr];
                Q[q].flag = false;
                q++;
    
                Q[q].l = tr;
                Q[q].r = tv[tl];
                Q[q].flag = false;
                q++;
    
                swap(tv[tl], tv[tr]);
            }
        }
        sort(h + 1, h + 1 + n);
        num = unique(h + 1, h + 1 + n) - h - 1;
        tot = 0;
        build(T[0], 1, num);
        for (int i = 1; i <= n; i++)
            update(T[i], T[i - 1], 1, num, lower_bound(h + 1, h + 1 + num, ptov[i]) - h, 1);
        for (int i = 1; i <= n; i++)
            S[i] = T[0];
        for (int i = 0; i < q; i++)
        {
            if (Q[i].flag)
            {
                if (Q[i].k == -1)
                    puts("0");
                else if (Q[i].k == 0)
                    printf("%d
    ", Q[i].r - Q[i].l + 1);
                else
                {
                    int tin = lower_bound(h + 1, h + 1 + num, in[Q[i].k]) - h;
                    auto tout = lower_bound(h + 1, h + 1 + num, out[Q[i].k]);
                    for (int j = Q[i].r; j; j -= lowbit(j))
                        ur[j] = S[j];
                    for (int j = Q[i].l - 1; j; j -= lowbit(j))
                        ul[j] = S[j];
                    int ans1 = query(Q[i].l - 1, Q[i].r, T[Q[i].l - 1], T[Q[i].r], 1, num, tout - h);
                    if (tin == 1)
                    {
                        if (*tout == out[Q[i].k])
                            printf("%d
    ", ans1);
                        else
                            printf("%d
    ", ans1 - 1);
                        continue;
                    }
                    for (int j = Q[i].r; j; j -= lowbit(j))
                        ur[j] = S[j];
                    for (int j = Q[i].l - 1; j; j -= lowbit(j))
                        ul[j] = S[j];
                    int ans2 = query(Q[i].l - 1, Q[i].r, T[Q[i].l - 1], T[Q[i].r], 1, num, tin - 1);
                    if (*tout == out[Q[i].k])
                        printf("%d
    ", ans1 - ans2);
                    else
                        printf("%d
    ", ans1 - 1 - ans2);
                }
            }
            else
            {
                add(Q[i].l, -1);
                ptov[Q[i].l] = Q[i].r;
                add(Q[i].l, 1);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Serialize and Deserialize Binary Tree
    sliding window substring problem汇总贴
    10. Regular Expression Matching
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第七章 链接
    程序员如何写一份合格的简历?(附简历模版)
    9个提高代码运行效率的小技巧你知道几个?
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第六章 存储器层次结构
    24张图7000字详解计算机中的高速缓存
    《深入理解计算机系统》(CSAPP)实验四 —— Attack Lab
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第五章 优化程序性能
  • 原文地址:https://www.cnblogs.com/Zeronera/p/11997580.html
Copyright © 2011-2022 走看看