题意

分析

把串倒过来插进trietrietrie上, 那么一个串的kpmkpmkpm串就是这个串在trietrietrie上对应的结点的子树下面的所有字符串.

那么像 BZOJ 3551/3545: [ONTAK2010]Peaks加强版 用dfsdfsdfs序+主席树就可以O(nlogn)O(nlogn)O(nlogn)解决查找子树第kkk小问题

但是与 BZOJ 3551/3545: [ONTAK2010]Peaks加强版 不同的是,这道题可能出现相同的串,于是在trietrietrie树上用链表把编号链起来就行了.



sbsbsb了,没想到超水的做法…geng4512的博客

CODE

#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; int flg = 1; for(;!isdigit(ch=getc());)if(ch=='-')flg=-flg;
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 100005;
const int MAXL = 300005;
const int MAXC = 26; int n, num[MAXN], trie_tot, in[MAXL], out[MAXL], tmr, seq[MAXN]; char s[MAXL]; struct seg { //主席树 seg *ls, *rs;
int sum; inline void* operator new (size_t, seg *Ls, seg *Rs, int _) {
static seg *mempool, *C;
if(C == mempool) mempool = (C = new seg[1<<15]) + (1<<15);
C->ls = Ls;
C->rs = Rs;
C->sum = _;
return C++;
} }*rt[MAXL]; struct O { //链表 O *nxt;
int v; inline void* operator new(size_t, O *Nxt, int _) {
static O *mempool, *C;
if(C == mempool) mempool = (C = new O[1<<15]) + (1<<15);
C->nxt = Nxt;
C->v = _;
return C++;
} }*head[MAXL]; struct trie { trie *ch[MAXC];
int v; inline void* operator new(size_t) {
static trie *mempool, *C;
if(C == mempool) mempool = (C = new trie[1<<15]) + (1<<15);
C->v = ++trie_tot;
return C++;
} }*root; inline void add(int x, int v) {
head[x] = new(head[x], v) O;
}
inline void insert(int id, int i) {
trie *r = root;
while(~i) {
if(!r->ch[s[i]-'a'])
r->ch[s[i]-'a'] = new trie;
r = r->ch[s[i]-'a'];
i--;
}
add(num[id] = r->v, id); //用链表链起来
} void dfs(trie *x) {
in[x->v] = tmr + 1;
for(O *i = head[x->v]; i; i = i->nxt)
seq[++tmr] = i->v;
for(int i = 0; i < MAXC; ++i)
if(x->ch[i]) dfs(x->ch[i]);
out[x->v] = tmr;
} seg* insert(seg *p, int l, int r, int x) {
if(l == r) return new(0x0, 0x0, p->sum+1) seg;
int mid = (l + r) >> 1;
if(x <= mid) return new(insert(p->ls, l, mid, x), p->rs, p->sum+1) seg;
else return new(p->ls, insert(p->rs, mid+1, r, x), p->sum+1) seg;
} inline int query(int i, int k) {
seg *x = rt[in[i]-1], *y = rt[out[i]];
if(y->sum - x->sum < k) return -1;
int l = 1, r = n, mid;
while(l < r) {
mid = (l + r) >> 1;
if(y->ls->sum - x->ls->sum >= k)
x = x->ls, y = y->ls, r = mid;
else k -= y->ls->sum - x->ls->sum, x = x->rs, y = y->rs, l = mid+1;
}
return l;
} int main () {
read(n); root = new trie;
for(int i = 1; i <= n; ++i) {
while(!isalpha(s[0]=getc())); int len = 0;
while(isalpha(s[++len]=getc()));
insert(i, len-1);
}
dfs(root);
rt[0] = new(0x0, 0x0, 0) seg; //初始化空树
rt[0]->ls = rt[0]->rs = rt[0];
for(int i = 1; i <= n; ++i)
rt[i] = insert(rt[i-1], 1, n, seq[i]); for(int i = 1, x; i <= n; ++i)
read(x), printf("%d\n", query(num[i], x));
}

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

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

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

  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. 关于SQLSERVER登录不了的情况

    是这样的,本人为了复制一个数据库文件把默认数据库设置成了脱机状态.在此点击联机的时候SSMS显示重启,重启后在用windows登录显示无法打开默认数据库.用其他不适该默认数据库的账号可以登录.想问一下 ...

  2. 使用mybatis出现异常:invalid comparison: java.time.LocalDateTime and java.lang.String

    整了半天终于找到问题所在:在mapper文件中,对该参数进行了和字符串的对比,如下: <if test="startTime != null and startTime != '' a ...

  3. WDS无人参与批量部署Ser 2008

    WDS无人参与批量部署Ser 2008 对于其它windows镜像采用此方法也是可以实现的: 1. 准备工作: 虚拟机server2012一个: 地址192.168.1.1/24 Server2008 ...

  4. python-day4(正式学习)

    数据类型 不同种类的变量值用不同的数据类型来描述 数字类型 整形:int 定义方式: name(变量名)=(赋值符号)180(变量值) name=int(180) 当变量值为小数时,自动向下取整 运算 ...

  5. Redis学习存档(1)——安装

    以虚拟机中的Linux系统(CentOS 6.5)中安装Redis为例 一.下载Redis 使用wget进行下载,可能部分系统不带wget命令,则yum下载即可 yum -y install wget ...

  6. .Net C# Dictionary 和参数字符串互转

    #region Parse #region Dictionary Parse To String /// <summary> /// Dictionary Parse To String ...

  7. poj 2891 模数不互质的中国剩余定理

    Strange Way to Express Integers Description Elina is reading a book written by Rujia Liu, which intr ...

  8. git 报错fatal: not a git repository (or any of the parent directories): .git

    产生原因:一般是没有初始化git本地版本管理仓库,所以无法执行git命令 解决方法:操作之前执行以下命令行:  git init 初始化git,即可解决:

  9. Python与C/C++相互调用(转)

    原文链接 作者 一.问题 Python模块和C/C++的动态库间相互调用在实际的应用中会有所涉及,在此作一总结. 二.Python调用C/C++ 1.Python调用C动态链接库 Python调用C库 ...

  10. java之JVM学习--简单理解编译和运行的过程之概览

    java代码编译流程图: java字节码执行由JVM执行引擎完成 Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码编译机制 类加载机制 类执行机制 Java源码编译机制 Jav ...