zoukankan      html  css  js  c++  java
  • [BZOJ 3439]Kpm的MC密码

    Description

    题库链接

    给出 (n) 个字符串,从 (1sim n) 编号。问对于每个字符串,以其作为后缀的第 (K_i) 小的字符串编号为多少。

    (1leq nleq 1000000,sumlimits_{i=1}^n lenth(string(i))leq 300000)

    Solution

    按照套路,把后缀变为前缀,显然是可以在 (Trie) 树上解决这个问题。

    而对于查询第 (K) 小,我们可以每个节点开一个权值线段树,遍历字符串时,就将路径上的权值线段树更新。

    其他的就是线段树和 (Trie) 树的操作了。

    Code

    //It is made by Awson on 2018.2.5
    #include <bits/stdc++.h>
    #define LL long long 
    #define dob complex<double>
    #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    #define writeln(x) (write(x), putchar('
    '))
    #define lowbit(x) ((x)&(-(x)))
    using namespace std; 
    const int N = 300000;
    const int M = 1000000;
    void read(int &x) {
        char ch; bool flag = 0;
        for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
        for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
        x *= 1-2*flag;
    }
    void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
    void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }
    
    int n, k, ans[M+5];
    char c[N+5];
    struct Segment_tree {
        int root[N+5], ch[N*20+5][2], key[N*20+5], pos;
        void insert(int &o, int l, int r, int loc) {
            if (!o) o = ++pos; ++key[o]; if (l == r) return;
            int mid = (l+r)>>1;
            if (loc <= mid) insert(ch[o][0], l, mid, loc);
            else insert(ch[o][1], mid+1, r, loc);
        }
        int query(int o, int l, int r, int k) {
            if (l == r) return l;
            if (key[o] < k) return -1; int mid = (l+r)>>1;
            if (key[ch[o][0]] < k) return query(ch[o][1], mid+1, r, k-key[ch[o][0]]);
            else return query(ch[o][0], l, mid, k);
        }
    }T;
    struct Trie {
        int ch[N+5][26], pos;
        void insert(int id) {
            int len = strlen(c), u = 0;
            for (int i = len-1; i >= 0; i--) {
                if (ch[u][c[i]-'a'] == 0) ch[u][c[i]-'a'] = ++pos;
                u = ch[u][c[i]-'a']; T.insert(T.root[u], 1, n, id);
            }
            ans[id] = u;
        }
    }Tr;
    
    void work() {
        read(n);
        for (int i = 1; i <= n; i++) {
            scanf("%s", c); Tr.insert(i);
        }
        for (int i = 1; i <= n; i++) {
            read(k); writeln(T.query(T.root[ans[i]], 1, n, k));
        }
    }
    int main() {
        work(); return 0;
    }
  • 相关阅读:
    新概念第二册(1)--英语口语听力课1
    外企面试课程(一)---熟悉常见的缩略词
    公司 邮件 翻译 培训 长难句 结课
    workflow
    公司 邮件 翻译 培训 长难句 20
    公司 邮件 翻译 培训 长难句 19
    Engineering Management
    公司 邮件 翻译 培训 长难句 18
    公司 邮件 翻译 培训 长难句 17
    第14.5节 利用浏览器获取的http信息构造Python网页访问的http请求头
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8419519.html
Copyright © 2011-2022 走看看