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组询问,每组询 ...
随机推荐
- AndroidRichText 让Textview轻松的支持富文本(图像ImageSpan、点击效果等等类似QQ微信聊天)
代码地址:https://github.com/Luction/AndroidRichText AndroidRichText帮助实现像QQ,微信一样的,一个TextView里既有文字又有表情又有图片 ...
- Xwindow的文章
http://blog.csdn.net/crond123/article/details/5733776 http://bbs.csdn.net/topics/90377015 http://bbs ...
- poj2454
我不会告诉你我对我自己的想法笑了一下午的.. #include <iostream> #include <algorithm> #include <time.h> ...
- .net MVC APi调用
常用的调用方法为Get/Post Get方法: 服务器 public string Get(int id) { return "value"; } 这个直接在网页就可以测试,用 h ...
- 【POJ】3523 The Morning after Halloween
1. 题目描述$m \times n$的迷宫(最大为$16 \times 16$)包含最多3个点,这些点可以同时向相邻方向移动或保持停止,使用小写字母表示起始位置,使用大写字母表示中止位置.求最少经过 ...
- OracleApps Dropship 流程
做的一个Dropship流程的实录(包括流程期间遇到问题的解决)What are the advantages of Drop Shipment Orders?These are the benefi ...
- Js获取日期时间及其它操作
var myDate = new Date();myDate.getYear(); //获取当前年份(2位)myDate.getFullYear(); //获取完整的年份(4位,1 ...
- SJ9012: IE6 IE7 不支持 JSON 对象
标准参考 JSON 是一种数据交换格式,RFC 4627 对 JSON 进行了详细描述. 根据 ECMA-262(ECMAScript)第 5 版中描述,JSON 是一个包含了函数 parse 和 s ...
- Java Web编程的主要组件技术——Struts入门
参考书籍:<J2EE开源编程精要15讲> Struts是一个开源的Java Web框架,很好地实现了MVC设计模式.通过一个配置文件,把各个层面的应用组件联系起来,使组件在程序层面联系较少 ...
- Java [Leetcode 189]Rotate Array
题目描述: Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the ...