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组询问,每组询 ...
随机推荐
- 使用pycharm开发web——django2.1.5(二)创建一个app并做一些配置
这里我学习的呢是刘江老师的站,主要原因在于他这个版本新,还比较细节 网址先留一手,约等于在引用http://www.liujiangblog.com/ 开始正题: 1.在pycharm界面终端命令行里 ...
- ubuntu 拨号上网
如果没有安装的用户,可以使用 sudo apt-get install pppoe pppoeconf 然后配置上网 sudo pppoeconf 最后,使用 sudo pon dsl-provide ...
- thinkphp5中的raw的作用
模板中输出变量 默认不展示HTMl 使用raw将其中的中的HTMl内容展示出来 <div class="content"> <div class="co ...
- 用python打开文件夹的三种方式
一.利用explorer.exe import os # 利用explorer.exe执行 start_directory = r'C:\代码\软件包' os.system("explore ...
- linux下mysql部署
mysql 1.拓扑结构 mysql集群有如下三层: 应用程序层:负责与mysql服务器通信的各种应用程序. Mysql服务器层:处理SQL命令,并与NDB存储引擎通信和Mysql服务器. NDB集群 ...
- django API返回中文乱码
renturn HttpResponse(json.dumps(data,ensure_ascii=False))
- C#学习基础资料记录---字典(Dictionary),时间表示方法(DateTime.Now),文件操作
1.字典 https://www.cnblogs.com/gengaixue/p/4002244.html 2.时间的表示方法 DateTime.Now的多种用法 https://www.cnblog ...
- X509证书在window server 2003/IIS 6环境部署
利用makecert.exe工具生成的X509证书在winform程序中运行正常,但是给部署在IIS中的应用程序用却获取不到证书信息,返回为空.原因是,iis没有权限读取位于证书存储区的X509证书, ...
- spring利用xml配置定时任务
在开发中会经常遇到做定时任务的需求,例如日志定时清理与处理,数据信息定时同步等需求. 1.在spring中利用xml配置定时任务,如下 <!-- ftpiptv信息同步接口定时任务配置--> ...
- ThreeJS中创建文字的几种方法
1. DOM + CSS 传统html5的文字实现,用于添加描述性叠加文字的方法.一般使用绝对定位,并且保证z-index够大,用于显示在3D场景之上. 优点: 与CSS3D效果一致 缺点: 3d效果 ...