把串倒过来插进trie上, 那么一个串的kpm串就是在以这个串最后一个为根的子树, 子树k大值的经典问题用dfs序+可持久化线段树就可以O(NlogN)解决

------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
 
using namespace std;
 
#define c(x) ((x) - 'a')
#define chk(x) ((x) >= 'a' && (x) <= 'z')
 
const int maxn = 100009;
const int maxl = 300009;
const int C = 26;
 
int V[maxn], seq[maxl], L[maxl], R[maxl];
int N, node_n, Val, n;
char s[maxl];
 
inline int read() {
char c = getchar();
int ret = 0;
for(; !isdigit(c); c = getchar());
for(; isdigit(c); c = getchar())
ret = ret * 10 + c - '0';
return ret;
}
 
struct O {
O* next;
int v;
} Opool[maxn], *Opt = Opool, *head[maxn];
 
inline O* AddO(int x, int v) {
Opt->v = v;
Opt->next = head[x];
return head[x] = Opt++;
}
 
struct node {
node *ch[C], *f;
O* t;
int n;
node() {
memset(ch, 0, sizeof ch);
f = 0;
t = 0;
}
} Pool[maxl], *Pt, *Rt;
 
inline node* newNode() {
Pt->n = node_n++;
return Pt++;
}
 
void Init_trie() {
node_n = 0;
Pt = Pool;
Rt = newNode();
}
 
void Insert(int x, int len) {
node* t = Rt;
while(len--) {
if(!t->ch[c(s[len])])
t->ch[c(s[len])] = newNode();
t = t->ch[c(s[len])];
}
t->t = AddO(V[x] = t->n, x + 1);
}
 
void Init() {
Init_trie();
n = 1;
N = read();
for(int i = 0; i < N; i++) {
int len = 0;
for(s[len] = getchar(); !chk(s[len]); s[len] = getchar());
for(s[++len] = getchar(); chk(s[len]); s[++len] = getchar());
Insert(i, len);
}
}
 
void DFS(node* t) {
L[t->n] = n + 1;
for(O* x = head[t->n]; x; x = x->next)
seq[++n] = x->v;
for(int i = 0; i < C; i++)
if(t->ch[i]) DFS(t->ch[i]);
R[t->n] = n;
}
 
struct Node {
Node *lc, *rc;
int v;
Node() {
lc = rc = 0;
}
} pool[maxl * 40], *pt, *Root[maxl];
 
void Init_sgt() {
Root[0] = (pt = pool)++;
Root[0]->lc = Root[0]->rc = Root[0];
Root[0]->v = 0;
}
 
Node* Modify(Node* t, int l, int r) {
Node* h = pt++;
h->v = t->v + 1;
if(l != r) {
int m = (l + r) >> 1;
if(Val <= m) {
h->lc = Modify(t->lc, l, m);
h->rc = t->rc;
} else {
h->lc = t->lc;
h->rc = Modify(t->rc, m + 1, r);
}
}
return h;
}
 
void Build() {
for(int i = 1; i <= n; i++) if(seq[i]) {
Val = seq[i];
Root[i] = Modify(Root[i - 1], 1, N);
} else
Root[i] = Root[i - 1];
}
 
int Query(int x, int Rk) {
Node *L = Root[::L[x] - 1], *R = Root[::R[x]];
if(R->v - L->v < Rk)
return -1;
int l = 1, r = N;
while(l < r) {
int m = (l + r) >> 1;
if(R->lc->v - L->lc->v < Rk) {
Rk -= R->lc->v - L->lc->v;
L = L->rc;
R = R->rc;
l = m + 1;
} else {
L = L->lc;
R = R->lc;
r = m;
}
}
return l;
}
 
void Work() {
for(int i = 0; i < N; i++)
printf("%d\n", Query(V[i], read()));
}
 
int main() {
Init();
DFS(Rt);
Init_sgt();
Build();
Work();
return 0;
}

------------------------------------------------------------------

3439: Kpm的MC密码

Time Limit: 15 Sec  Memory Limit: 256 MB
Submit: 311  Solved: 153
[Submit][Status][Discuss]

Description

背景

想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的。。。),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身份验证问题了。。。

描述

Kpm当年设下的问题是这样的:

现在定义这么一个概念,如果字符串s是字符串c的一个后缀,那么我们称c是s的一个kpm串。

系统将随机生成n个由a…z组成的字符串,由1…n编号(s1,s2…,sn),然后将它们按序告诉你,接下来会给你n个数字,分别为k1…kn,对于每一个ki,要求你求出列出的n个字符串中所有是si的kpm串的字符串的编号中第ki小的数,如果不存在第ki小的数,则用-1代替。(比如说给出的字符串是cd,abcd,bcd,此时k1=2,那么”cd”的kpm串有”cd”,”abcd”,”bcd”,编号分别为1,2,3其中第2小的编号就是2)(PS:如果你能在相当快的时间里回答完所有n个ki的查询,那么你就可以成功帮kpm进入MC啦~~)

Input

第一行一个整数 n 表示字符串的数目

接下来第二行到n+1行总共n行,每行包括一个字符串,第i+1行的字符串表示编号为i的字符串

接下来包括n行,每行包括一个整数ki,意义如上题所示

Output

包括n行,第i行包括一个整数,表示所有是si的kpm串的字符串的编号中第ki小的数

Sample Input

3
cd
abcd
bcd
2
3
1

Sample Output

2
-1
2

样例解释

“cd”的kpm 串有”cd”,”abcd”,”bcd”,编号为1,2,3,第2小的编号是

2,”abcd”的kpm串只有一个,所以第3小的编号不存在,”bcd”的kpm

串有”abcd”,”bcd”,第1小的编号就是2。

数据范围与约定

设所有字符串的总长度为len

对于100%的数据,1<=n<=100000,0

HINT

Source

BZOJ 3439: Kpm的MC密码( trie + DFS序 + 主席树 )的更多相关文章

  1. BZOJ 3439: Kpm的MC密码 (trie+dfs序主席树)

    题意 略 分析 把串倒过来插进trietrietrie上, 那么一个串的kpmkpmkpm串就是这个串在trietrietrie上对应的结点的子树下面的所有字符串. 那么像 BZOJ 3551/354 ...

  2. bzoj 3439: Kpm的MC密码 Trie+动态开点线段树

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3439 题解: 首先我们发现这道题要查的是后缀不是前缀. 如果查前缀就可以迅速查找到字符串 ...

  3. BZOJ 3439 Kpm的MC密码 (Trie树+线段树合并)

    题面 先把每个串反着插进$Trie$树 每个节点的子树内,可能有一些节点是某些字符串的开头 每个节点挂一棵权值线段树,记录这些节点对应的原来字符串的编号 查询的时候在线段树上二分即可 为了节省空间,使 ...

  4. BZOJ 3439 Kpm的MC密码

    倒着建trie,然后主席树来求子树第k大. #include<iostream> #include<cstdio> #include<cstring> #inclu ...

  5. bzoj 3439 Kpm的MC密码(Trie+dfs序+主席树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3439 [题意] 给定若干串,问一个串的作为其后缀的给定串集合中的第k小. [思路] 如 ...

  6. BZOJ-3439:Kpm的MC密码(Trie+DFS序+主席树)

    背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身份验证问题了... 描述 ...

  7. dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448

    4448: [Scoi2015]情报传递 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 588  Solved: 308[Submit][Status ...

  8. 2018.09.30 bzoj3551:Peaks加强版(dfs序+主席树+倍增+kruskal重构树)

    传送门 一道考察比较全面的题. 这道题又用到了熟悉的kruskal+倍增来查找询问区间的方法. 查到询问的子树之后就可以用dfs序+主席树统计答案了. 代码: #include<bits/std ...

  9. 【bzoj3545/bzoj3551】[ONTAK2010]Peaks/加强版 Kruskal+树上倍增+Dfs序+主席树

    bzoj3545 题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询 ...

随机推荐

  1. iOS 唯一设备号

    https://github.com/fabiocaccamo/FCUUID 目前比较好的解决方案.

  2. Euro Efficiency(完全背包)

    Euro Efficiency Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 20000/10000K (Java/Other) Tot ...

  3. POJ1042 Gone Fishing

    采用贪心策略. 假设他从1湖泊走到x 湖泊,这还剩下 h*12 - sigma(T1--Tx-1).(单位时间为5分钟).然后再用剩下的时间去钓1-x的湖泊的鱼. 每次都选择最多鱼的湖泊钓. code ...

  4. 浏览器返回按钮不会触发onLoad事件

    最近在做一个移动端项目,发现移动端某些返回和PC端是有差异的, 比如ios中返回按钮是直接使用缓存的, 不会执行任何js代码, 这个问题很蛋疼, 例如, 在提交的时候将按钮设置为loading状态, ...

  5. c++中,保证头文件只被编译一次,避免多重包含的方法

    保证头文件只被编译一次 #pragma once这是一个比较常用的C/C++杂注,只要在头文件的最开始加入这条杂注,就能够保证头文件只被编译一次. #pragma once是编译器相关的,有的编译器支 ...

  6. css学习知识点

    各个前缀所代表的浏览器: Webkit: chrome, safari[也有可能是opera] Moz: 火狐 Ms: 主要是IE O: opera border-radius:  IE9  -web ...

  7. C++引用和函数返回值

    这是老师上课讲的内容,现在把它写下来,一方面当做复习,另一方面真的想学点东西.废话不多说,先贴上测试的代码: #include <iostream.h> float temp; float ...

  8. nodeJs入门笔记(二)

    js中window通常是全局变量 global 是node.js里的全局变量 node中能访问的对象一般都是 global的 属性 global 对象属性 process 用于描述当前Node 进程状 ...

  9. css书写顺序和常用命名推荐

    写代码的时候有一个好的规范和顺序能够帮你节省很多时间.下文将推荐相关CSS书写顺序和规范的一些方法.这个文档将会整理进前端规范文档中,如果你有更好的意见,不妨留言告知我们. CSS书写顺序 该代码来自 ...

  10. 服务端NETTY 客户端非NETTY处理粘包和拆包的问题

    之前为了调式和方便一直没有处理粘包的问题,今天专门花了时间来搞NETTY的粘包处理,要知道在高并发下,不处理粘包是不可能的,数据流的混乱会造成业务的崩溃什么的我就不说了.所以这个问题 在我心里一直是个 ...