BZOJ 3439: Kpm的MC密码 (trie+dfs序主席树)
题意
略
分析
把串倒过来插进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序主席树)的更多相关文章
- BZOJ 3439: Kpm的MC密码( trie + DFS序 + 主席树 )
把串倒过来插进trie上, 那么一个串的kpm串就是在以这个串最后一个为根的子树, 子树k大值的经典问题用dfs序+可持久化线段树就可以O(NlogN)解决 --------------------- ...
- bzoj 3439: Kpm的MC密码 Trie+动态开点线段树
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3439 题解: 首先我们发现这道题要查的是后缀不是前缀. 如果查前缀就可以迅速查找到字符串 ...
- BZOJ 3439 Kpm的MC密码 (Trie树+线段树合并)
题面 先把每个串反着插进$Trie$树 每个节点的子树内,可能有一些节点是某些字符串的开头 每个节点挂一棵权值线段树,记录这些节点对应的原来字符串的编号 查询的时候在线段树上二分即可 为了节省空间,使 ...
- BZOJ 3439 Kpm的MC密码
倒着建trie,然后主席树来求子树第k大. #include<iostream> #include<cstdio> #include<cstring> #inclu ...
- bzoj 3439 Kpm的MC密码(Trie+dfs序+主席树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3439 [题意] 给定若干串,问一个串的作为其后缀的给定串集合中的第k小. [思路] 如 ...
- BZOJ-3439:Kpm的MC密码(Trie+DFS序+主席树)
背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当然地忘记了密码,只能来解答那些神奇的身份验证问题了... 描述 ...
- dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448
4448: [Scoi2015]情报传递 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 588 Solved: 308[Submit][Status ...
- 2018.09.30 bzoj3551:Peaks加强版(dfs序+主席树+倍增+kruskal重构树)
传送门 一道考察比较全面的题. 这道题又用到了熟悉的kruskal+倍增来查找询问区间的方法. 查到询问的子树之后就可以用dfs序+主席树统计答案了. 代码: #include<bits/std ...
- 【bzoj3545/bzoj3551】[ONTAK2010]Peaks/加强版 Kruskal+树上倍增+Dfs序+主席树
bzoj3545 题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询 ...
随机推荐
- Java--垃圾回收【转载】
一:垃圾回收机制的意义 java 语言中一个显著的特点就是引入了java回收机制,可以有效的防止内存泄露,有效的使用空闲的内存. 内存泄露:指该内存空间使用完毕后未回收,在不涉及复杂数据结构的一般情况 ...
- DP的初级问题——01包、最长公共子序列、完全背包、01包value、多重部分和、最长上升子序列、划分数问题、多重集组合数
当初学者最开始学习 dp 的时候往往接触的是一大堆的 背包 dp 问题, 那么我们在这里就不妨讨论一下常见的几种背包的 dp 问题: 初级的时候背包 dp 就完全相当于BFS DFS 进行搜索之后的记 ...
- fiddler笔记:filters选项卡
Host Show only Intranet Host 只显示内网(如不带"."的主机名)的数据流. Show only Internet Host 只显示互联网(如不带&quo ...
- php 压缩接口
function rtnJson($obj) { if (!headers_sent() && // 如果页面头部信息还没有输出 extension_loaded("zlib ...
- MyBatis 示例-主键回填
测试类:com.yjw.demo.PrimaryKeyTest 自增长列 数据库表的主键为自增长列,在写业务代码的时候,经常需要在表中新增一条数据后,能获得这条数据的主键 ID,MyBatis 提供了 ...
- gzip: stdin: not in gzip format 解决办法
# sudo tar zxvf ./jdk-7ull-linux-i586.tar.gz -C /usr/lib/jvm gzip: stdin: not in gzip format tar: Ch ...
- selenium 12306模拟登陆
代码应用场景 :基于第三方打码网站模拟登陆12306 验证码识别 基于第三方平台超级鹰识别 超级鹰官网:http://www.chaojiying.com/user/ 超级鹰使用流程: 注册 登陆(用 ...
- BootStrap【四、插件】
BootStrap插件基于: 1.BootStrap.js 2.BootStrap.js基于JQuery data属性 1.通过data属性控制页面交互 2.$(document).off('.dat ...
- 在php中连接数据库 pdo
在php中连接数据库 pdo //数据库信息 $mysql_conf = array( 'host' => '127.0.0.1', 'db' => 'meteorolog_foreign ...
- elasticsearch 数据备份
ES数据备份找了一些方法,发现elasticdump 这个工具不错 elasticdump --input=http://192.168.0.92:9200/hs2840 --output ./hs2 ...