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组询问,每组询 ...
随机推荐
- XE2编译出来的DLL的DLLMain的退出地方用到了halt0
DelphiXE2内存加模块升级版.支持32位和64位模块. 已转至新的博客 http://www.raysoftware.cn/?p=51 很多年以前写过内存加载DLL的一片技术. http://b ...
- YASKAWA电机控制(1)---接线
实验室所购置电机型号为YASKAWA-AC SERVO MOTOR SGM7J-01AFC6S型,配SGD7S-R90A00A002伺服控制器.电机和控制器的操作说明书由安川中文官网安川电机资料提供. ...
- Map集合案例
1.获取字符串中每一个字母出现的次数. 比如"aababcabcdabcde",结果为:a(5)b(4)c(3)d(2)e(1) 分析如下: package mapexercise ...
- useradd和adduser的区别
1. 在root权限下,useradd只是创建了一个用户名,如 (useradd +用户名 ),它并没有在/home目录下创建同名文件夹,也没有创建密码,因此利用这个用户登录系统,是登录不了的,为了 ...
- Internet Explorer for Mac the Easy Way: Run IE 7, IE8, & IE9 Free in a Virtual Machine
From link: http://osxdaily.com/2011/09/04/internet-explorer-for-mac-ie7-ie8-ie-9-free/ If you’re ...
- SGU 275 To xor or not to xor (高斯消元)
题目链接 题意:有n个数,范围是[0, 10^18],n最大为100,找出若干个数使它们异或的值最大并输出这个最大值. 分析: 一道高斯消元的好题/ 我们把每个数用二进制表示,要使得最后的异或值最大, ...
- 试图从数据库 ‘UFData_001_2003' 中提取的逻辑页 (1:10720) 属于对象 '0',而非对象 'syscolumns'
数据库可以使用,可以备份,但对备份进行恢复时报错,使用sp_attach_db对两个物理文件进行连接时,报同样错误: 服务器: 消息 605,级别 21,状态 1,行 1 试图从数据库 ‘UFData ...
- codeforces 333B - Chips
注意:横向纵向交叉时,只要两条边不是正中的边(当n&1!=1),就可以余下两个chip. 代码里数组a[][]第二维下标 0表示横向边,1表示纵向边. #include<stdio.h& ...
- UVA 11426 GCD-Extreme(II) ★ (欧拉函数)
题意 求Σ{1<=i<N} Σ{i<j<=N} GCD(i, j) (N<=4000000) 分析 原始思路 暴力求明显是不行的,我们把式子简化形式一下发现它可以 ...
- 【C#学习笔记】函数重载
using System; namespace ConsoleApplication { class Program { static void Print(int a, int b) { Conso ...