• BZOJ3439 Kpm的MC密码


    云神出的题= =,逼得蒟蒻要跳楼了

    这道题的话。。。先把读入的字符串反转,然后建trie树

    发现一个字符串的kpm串就是他的结尾字符的子树,于是对所有是字符串结尾的点按照dfs序展成一个序列。

    问题转化为求区间第k大,用主席树什么的就好了。。。

      1 /**************************************************************
      2     Problem: 3439
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:1500 ms
      7     Memory:62744 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <vector>
     13 #include <algorithm>
     14  
     15 using namespace std;
     16 typedef vector <int> Vec;
     17 const int N = 100005;
     18 const int Len = 300005;
     19 const int M = 2000005;
     20  
     21 struct trie_node {
     22     int son[26], st, ed;
     23     Vec tail;
     24 } t[Len];
     25  
     26 struct seg_node {
     27     int lson, rson, num;
     28 } tr[M];
     29  
     30 int n, cnt_trie = 1, cnt_seq, cnt_seg;
     31 int Tail[N], root[N];
     32 char st[Len];
     33 int len;
     34 inline void read() {
     35     char ch = getchar();
     36     while (ch < 'a' || 'z' < ch) ch = getchar();
     37     len = 0;
     38     while ('a' <= ch && ch <= 'z')
     39         st[++len] = ch, ch = getchar();
     40 }
     41  
     42 #define ch(j) (int) st[j] - 'a'
     43 void build_trie() {
     44     int i, j, now;
     45     for (i = 1; i <= n; ++i) {
     46         read();
     47         reverse(st + 1, st + len + 1);
     48         now = 1;
     49         for (j = 1; j <= len; ++j) {
     50             if (!t[now].son[ch(j)])
     51                 t[now].son[ch(j)] = ++cnt_trie;
     52             now = t[now].son[ch(j)];
     53         }
     54         Tail[i] = now, t[now].tail.push_back(i);
     55     }
     56 }
     57  
     58 #define mid (l + r >> 1)
     59 void insert(int &p, int l, int r, int pos) {
     60     tr[++cnt_seg] = tr[p], p = cnt_seg, ++tr[p].num;
     61     if (l == r) return;
     62     if (pos <= mid) insert(tr[p].lson, l, mid, pos);
     63     else insert(tr[p].rson, mid + 1, r, pos);
     64 }
     65  
     66 int query(int i, int j, int rank) {
     67     i = root[i - 1], j = root[j];
     68     if (tr[j].num - tr[i].num < rank) return -1;
     69     int l = 1, r = n;
     70     while (l != r) {
     71         if (tr[tr[j].lson].num - tr[tr[i].lson].num >= rank)
     72             r = mid, i = tr[i].lson, j = tr[j].lson;
     73         else {
     74             rank -= tr[tr[j].lson].num - tr[tr[i].lson].num;
     75             l = mid + 1, i = tr[i].rson, j = tr[j].rson;
     76         }
     77     }
     78     return l;
     79 }
     80  
     81 void dfs(int p) {
     82     int i, sz = t[p].tail.size();
     83     if (sz) {
     84         t[p].st = ++cnt_seq, root[cnt_seq] = root[cnt_seq - 1];
     85         for (i = 0; i < sz; ++i)
     86             insert(root[cnt_seq], 1, n, t[p].tail[i]);
     87     }
     88     for (i = 0; i < 26; ++i)
     89         if (t[p].son[i])
     90             dfs(t[p].son[i]);
     91     if (sz)
     92         t[p].ed = cnt_seq;
     93 }
     94  
     95 int main() {
     96     int i, x;
     97     scanf("%d
    ", &n);
     98     build_trie();
     99     dfs(1);
    100     for (i = 1; i <= n; ++i) {
    101         scanf("%d", &x);
    102         printf("%d
    ", query(t[Tail[i]].st, t[Tail[i]].ed, x));
    103     }
    104 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    MySQL数据库的常用命令
    函数返回 局部变量问题
    几种网络I/O模型
    socket的select模型【摘】
    Linux Bash Shell入门教程【转载】
    Shell学习【转】
    unicode 2 utf8 [转]
    linux下多线程的创建与等待详解 【转载】
    运算(93&-8)的结果
    一道腾讯的面试题,关于a和&a
  • 原文地址:https://www.cnblogs.com/rausen/p/4135424.html
Copyright © 2020-2023  润新知