BZOJ-3439:Kpm的MC密码(Trie+DFS序+主席树)
背景
想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
题意:Trie树上,求某个点的子树的第K大。
思路:建立Trie树,然后跑得dfs序,然后主席树求第k大。
( 注意当Trie树上一个点代表多个串时,怎么去处理dfs序。
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int ch[maxn][],cnt,in[maxn],out[maxn],times,tot,np;
int Laxt[maxn],Next[maxn],To[maxn],a[maxn],rt[maxn];
char c[maxn];
struct node{
int l,r,sum;
node(){ l=r=sum=;}
node(int ll,int rr,int ss):l(ll),r(rr),sum(ss){}
}s[maxn*];
void add(int u,int v){
Next[++tot]=Laxt[u];
Laxt[u]=tot; To[tot]=v;
}
void insert(int opt)
{
int L=strlen(c+),Now=;
for(int i=L;i>=;i--){
if(!ch[Now][c[i]-'a']) ch[Now][c[i]-'a']=++cnt;
Now=ch[Now][c[i]-'a'];
}
add(Now,opt);
}
void dfs(int u)
{ //Trie树上同一个点可能有多个串,把他们一起排。
int num=times;
for(int i=Laxt[u];i;i=Next[i]) a[++times]=To[i];
for(int i=;i<;i++) if(ch[u][i]) dfs(ch[u][i]);
for(int i=Laxt[u];i;i=Next[i]) in[To[i]]=num,out[To[i]]=times;
}
void modify(int &Now,int pre,int L,int R,int pos)
{
Now=++np; s[Now]=node(s[pre].l,s[pre].r,s[pre].sum+);
if(L==R) return;
int Mid=(L+R)>>;
if(pos<=Mid) modify(s[Now].l,s[pre].l,L,Mid,pos);
else modify(s[Now].r,s[pre].r,Mid+,R,pos);
}
int query(int Now,int pre,int L,int R,int K)
{
if(s[Now].sum-s[pre].sum<K) return -;
if(L==R) return L;
int Mid=(L+R)>>;
if(s[s[Now].l].sum-s[s[pre].l].sum>=K) return query(s[Now].l,s[pre].l,L,Mid,K);
return query(s[Now].r,s[pre].r,Mid+,R,K-(s[s[Now].l].sum-s[s[pre].l].sum));
}
int main()
{
int N,K,i,j;
scanf("%d",&N);
for(i=;i<=N;i++){
scanf("%s",c+);
insert(i);
}
dfs();
for(i=;i<=N;i++){
modify(rt[i],rt[i-],,N,a[i]);
}
for(i=;i<=N;i++){
scanf("%d",&K);
int ans=query(rt[out[i]],rt[in[i]],,N,K);
printf("%d\n",ans);
}
return ;
}
BZOJ-3439:Kpm的MC密码(Trie+DFS序+主席树)的更多相关文章
- BZOJ 3439: Kpm的MC密码( trie + DFS序 + 主席树 )
把串倒过来插进trie上, 那么一个串的kpm串就是在以这个串最后一个为根的子树, 子树k大值的经典问题用dfs序+可持久化线段树就可以O(NlogN)解决 --------------------- ...
- BZOJ 3439: Kpm的MC密码 (trie+dfs序主席树)
题意 略 分析 把串倒过来插进trietrietrie上, 那么一个串的kpmkpmkpm串就是这个串在trietrietrie上对应的结点的子树下面的所有字符串. 那么像 BZOJ 3551/354 ...
- 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小. [思路] 如 ...
- 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组询问,每组询 ...
随机推荐
- CA认证原理以及实现(下)
在上述的文章后了解到原理之后,我们这篇文章来进行CA的搭建. OPEN SSL 环境搭建在基础原理中我们提到了两种认证服务,单项认证服务和双向认证服务,我们就以双向认证服务举例说明.OpenSSL是一 ...
- CapIp.pas
unit CapIp; interface uses Windows, Messages,Classes,winsock,sysutils; const WM_CapIp = WM_USER + ; ...
- 【层次查询】Hierarchical Queries之亲兄弟间的排序(ORDER SIBLINGS BY)
http://blog.itpub.net/519536/viewspace-624176 有关层次查询之前的文章参考如下. [层次查询]Hierarchical Queries之"树的遍历 ...
- HDU3572Task Schedule(最大流 ISAP比較快)建图方法不错
Task Schedule Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- 怎样隐藏Windows7 系统保留分区
安装Windows7操作系统时须要预留出100MB左右的系统保留盘分区.在Windows7激活是必须给它分配盘符,否则无法将其成功激活,但是激活后该盘符永久地显示了出来,怎样将其隐藏掉呢? 1.隐藏前 ...
- Android——通过Intent传递一些二进制数据的方法有哪些
1.方法 (1)使用Serializable接口实现序列化.利用Bundle.putSerializable(Key, Object);这里objec对象需要实现serializable接口. (2) ...
- flex 节点删除
<mx:Script> <![CDATA[ protected function btn1_clickHandler(evt:MouseEvent ...
- bootstrap到底是用来做什么的(概念)
Bootstrap官网:http://v3.bootcss.com/ Bootstrap是Twitter推出的一个用于前端开发的开源工具包.它由Twitter的设计师Mark Otto和Jacob T ...
- unix改变shell显示颜色
编写shell脚本的时候.通过改变shell的显示颜色,不但可以改变使用shell终端的体验,并且更为有用的是,可以通过改变显示内容的颜色来区分正常输出.warning和error等不同关注级别的输出 ...
- linux 块设备驱动(五)——块设备应用层的操作
一: 加载好sbull驱动 root@CarRadio:/# ls /dev/sbull -l brw-r--r-- 1 root root 254, 16 Mar 25 08:25 /dev/sbu ...