题意

分析

把串倒过来插进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. sysconf获取系统参数

    头文件: #include <unistd.h> 原型:long sysconf(int sysnum); 示例: #include <stdio.h> #include &l ...

  2. Hadoop和Spark的Shuffer过程对比解析

    Hadoop Shuffer Hadoop 的shuffer主要分为两个阶段:Map.Reduce. Map-Shuffer: 这个阶段发生在map阶段之后,数据写入内存之前,在数据写入内存的过程就已 ...

  3. session和cookie区别,多台WEB服务器如何共享session,禁用COOKIE后SESSION是否可用,为什么?

    答:session的运行机制: 用户A访问站点Y,如果站点Y指定了session_start();(以下假设session_start()总是存在)那么会产生一个session_id,这个sessio ...

  4. selenium弹框元素定位-冻结界面

    有些网站上面的元素,我们鼠标放在上面,会动态弹出一些内容. 比如,百度首页的右上角,有个更多产品选项,如下图所示: 如果我们把鼠标放在上边,就会弹出下面的百度营销.音乐.图片等图标. 如果我们要用se ...

  5. python 基础(十五)--time和datatime模块

    time模块 time.time():返回当前时间,时间戳 time.clock():返回cpu时间(?),当有time.sleep()时,time.clock()不计时 time.localtime ...

  6. NAT 模式下有两个虚拟机 网段不一样,一台可上网,可ping通,一台上不了网且ping不通

    NAT 模式下有两个虚拟机 网段不一样,一台可上网,可ping通,一台上不了网且ping不通直接修改网段的话,会登录不上去,解决方法:设置>网络适配器>高级>生成mac地址重新登陆即 ...

  7. android 自定义控件之NetWorkImageView 处理listview等控件中的图片加载乱序问题

    0.调用: BaseAdapter中设置方法 holder.iv.loadImage(url); adapter_xxx.xml 中 控件需要用 xxx.NetWorkImageView 1 NetW ...

  8. spring——自动装配

    语法:<bean id="..." class="..." autowire="byType"/> autowire属性取值如下 ...

  9. BMP RGB888转RGB565 +上下翻转+缩放

      典型的BMP图像文件由四部分组成: (1) 位图头文件数据结构,它包含BMP图像文件的类型.文件大小和位图起始位置等信息: typedef struct tagBITMAPFILEHEADER { ...

  10. SQL连接(join)

    INNER JOIN:如果表中有至少一个匹配,则返回行 LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行 RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行 FULL JOIN ...