bzoj 3439 Kpm的MC密码(Trie+dfs序+主席树)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=3439
【题意】
给定若干串,问一个串的作为其后缀的给定串集合中的第k小。
【思路】
如果将每个串反向,则问题为一个串作为其前缀的给定串集合的第k小。
如果用Trie组织数据,则发现该串对应的集合即为以Trie上以尾节点为根的子树。我们按照dfs序构造序列,则问题即为连续区间上的第k大,可以用主席树求出。
注意有重复的串。
【代码】
#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 1e6+; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} char s[N];
int n,m,dfsc,L[N],R[N],dfs_list[N],sz; struct Trie {
int ch[N][],sz;
vector<int> num[N];
Trie() {
sz=;
memset(ch,,sizeof(ch));
}
void insert(char *s,int val) {
int u=;
for(int i=;s[i];i++) {
int c=s[i]-'a';
if(!ch[u][c]) ch[u][c]=++sz;
u=ch[u][c];
}
num[u].push_back(val);
}
void dfs(int u)
{
int tmp=dfsc+;
FOR(i,,(int)num[u].size()-) {
dfs_list[++dfsc]=num[u][i];
L[num[u][i]]=tmp;
}
FOR(c,,) if(ch[u][c])
dfs(ch[u][c]);
FOR(i,,(int)num[u].size()-)
R[num[u][i]]=dfsc;
}
} trie; struct Tnode {
Tnode *ch[];
int num;
void * operator
new(size_t size,Tnode *l,Tnode *r,int x) ;
}*T[N],*mempool,*G;
//´óСΪ 1<<15 µÄÄÚ´æ³Ø
void *Tnode::operator new (size_t size,Tnode *l,Tnode*r,int x) {
if(G==mempool) {
G=new Tnode[<<];
mempool=G+(<<);
memset(G,,sizeof(Tnode)*(<<));
}
G->ch[]=l,G->ch[]=r,G->num=x;
return G++;
} Tnode* build(Tnode* p,int l,int r,int val) {
int mid=l+r>>;
if(l==r) return new (0x0,0x0,p->num+)Tnode;
if(val<=mid)
return new (build(p->ch[],l,mid,val),p->ch[],p->num+)Tnode;
else
return new (p->ch[],build(p->ch[],mid+,r,val),p->num+)Tnode;
}
int query(Tnode *x,Tnode *y,int l,int r,int rk) {
int mid=l+r>>;
if(l==r) return mid;
int sum=y->ch[]->num - x->ch[]->num;
if(rk<=sum) return query(x->ch[],y->ch[],l,mid,rk);
else return query(x->ch[],y->ch[],mid+,r,rk-sum);
} int main()
{
n=read();
FOR(i,,n) {
scanf("%s",s);
int n=strlen(s);
for(int j=;j*<n;j++)
swap(s[j],s[n--j]);
trie.insert(s,i);
}
trie.dfs(); T[]=new (0x0,0x0,) Tnode;
T[]->ch[]=T[]->ch[]=T[]; FOR(i,,n)
T[i]=build(T[i-],,n,dfs_list[i]);
FOR(i,,n) {
int k=read();
if(k>R[i]-L[i]+) puts("-1");
else printf("%d\n",query(T[L[i]-],T[R[i]],,n,k));
}
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序+主席树)
背景 想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组询问,每组询 ...
随机推荐
- [Python]读写文件方法
http://www.cnblogs.com/lovebread/archive/2009/12/24/1631108.html [Python]读写文件方法 http://www.cnblogs.c ...
- Java类的加载、链接和初始化
一.Java的类加载机制回顾与总结: 我们知道一个Java类要想运行,必须由jvm将其装载到内存中才能运行,装载的目的就是把Java字节代码转换成JVM中的java.lang.Class类的对象.这样 ...
- C++:类型转换
5.3 类型转换 5.3.1 系统预定义类型间的转换 1. 隐式转换: 例如: int x=5,y; y=3.5+x; //系统会自动先将int型的5转换为double型的5. ...
- 如何禁用 radio ,设置为只读,不能选定
如何禁用 radio ,设置为只读,不能选定 禁用 radio ,设置为只读,不能选定: <input name="gender" type="radio" ...
- WPF中Timer与DispatcherTimer类的区别
前几天在WPF中写了一个轨迹回放的功能,我想稍微做过类似项目的,都晓得采用一个时间控件或者时间对象作为调度器,我在这么做的时候,出现了问题,于是将程序中的Timer换成了DispatchTimer,然 ...
- Hibernate 多表关联
hibernate中可以一次对多个表进行数据插入,这种插入类似 Hibernate的关联映射关系有:多对一 ---- many-to-one一对多 ---- one-to-many一对一 ---- o ...
- 轻量级MVC标准
看到标题,估计有人就开始想吐了,没关系,你可以先吐完再看,现在MVC框架多如牛毛,没必要再重复发明轮子了,要声明的是,这里不是想要发明轮子,也没那个闲工夫去发明轮子,而是看到这么多MVC框架模样都差不 ...
- 车牌识别LPR系统系列文章汇总
这里的LPR的的几篇文章是之前项目的一些相关资料的整理,涉及实验室内部的资料就没有放上来,希望能对想了解这方面的同学,有所帮助,那怕了解个大概也好.知道整体的思路就好.当初就是一个人瞎摸索,走了很多的 ...
- netty websocket协议开发
websocket的好处我们就不用多说了,就是用于解决长连接.服务推送等需要的一种技术. 以下我们来看一个例子: package com.ming.netty.http.websocket; impo ...
- netty 解决TCP粘包与拆包问题(三)
今天使用netty的固定长度进行解码 固定长度解码的原理就是按照指定消息的长度对消息自动解码. 在netty实现中,只需要采用FiexedLengthFrameDecoder解码器即可... 以下是服 ...