【BZOJ3439】Kpm的MC密码,trie树+dfs序+主席树
来源:互联网 发布:linux oracle安装在哪 编辑:程序博客网 时间:2024/04/29 07:16
Time:2016.05.07
Author:xiaoyimi
转载注明出处谢谢
传送门
思路:
1.have a trie,还得是倒着建的,记录每个结尾节点的id(可能会有重复,所以开一个vector记录一下)
2.对trie树进行dfs序,记录结尾节点的子树区间
3.建立主席树(由于权值就是id标号,所以不用离散化了)
4.1-n依次查询即可
注意:
dfs序在遇到结尾节点时才++记录序号的变量cnt,而且相同串的dfs序号是一样的(就是说一个结尾节点可能包含好多个不同编号的串),左区间取最前的一个(比如dfs到x节点,编号为2,x节点存着两个串,那么它们的左区间都为2,而序号要加两次)
代码:
#include<bits/stdc++.h>using namespace std;#define M 100004#define ls(x) a[x].ch[0]#define rs(x) a[x].ch[1]int n,m,cnt,root=M*3-10;int trie[M*3][26],num[M*3],Ls[M],Rs[M],data[M];vector <int> q[M*3];char s[M*3];struct Chairman_tree{ int siz,ch[2];}a[M*18];int in(){ int t=0;char ch=getchar(); while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) t=(t<<3)+(t<<1)+ch-48,ch=getchar(); return t;}void build(int now,int L,int R,int rt,int val){ a[rt].siz=a[now].siz+1; if (L==R) return; int mid=(L+R)>>1; if (mid>=val) rs(rt)=rs(now), ls(rt)=++cnt, build(ls(now),L,mid,ls(rt),val); else ls(rt)=ls(now), rs(rt)=++cnt, build(rs(now),mid+1,R,rs(rt),val);}int get(int begin,int end,int L,int R,int k){ if (begin==end) return end; int mid=(begin+end)>>1,t=a[ls(R)].siz-a[ls(L)].siz; if (k<=t) return get(begin,mid,ls(L),ls(R),k); else return get(mid+1,end,rs(L),rs(R),k-t);}void insert(int id,char s[]){ int len=strlen(s),now=root; for (int i=len-1;i>=0;i--) { if (!trie[now][s[i]-'a']) trie[now][s[i]-'a']=++cnt; now=trie[now][s[i]-'a']; } num[now]++; q[now].push_back(id);}void dfs(int x){ if (num[x]) { for (int i=0;i<num[x];i++) Ls[q[x][i]]=cnt+1; for (int i=0;i<num[x];i++) data[++cnt]=q[x][i]; } for (int i=0;i<26;i++) if (trie[x][i]) dfs(trie[x][i]); for (int i=0;i<num[x];i++) Rs[q[x][i]]=cnt;}main(){ n=in(); for (int i=1;i<=n;i++) scanf("%s",s), insert(i,s); cnt=0; dfs(root); cnt=n+1; int k; for (int i=1;i<=n;i++) build(i,1,n,i+1,data[i]); for (int i=1;i<=n;i++) { k=in(); if (a[Rs[i]+1].siz-a[Ls[i]].siz<k) printf("-1\n"); else printf("%d\n",get(1,n,Ls[i],Rs[i]+1,k)); }}
0 0
- 【BZOJ3439】Kpm的MC密码,trie树+dfs序+主席树
- 【bzoj3439】Kpm的MC密码 trie树+主席树
- 【BZOJ3439】Kpm的MC密码 Trie+dfs序+可持久化线段树
- BZOJ_P3439 Kpm的MC密码(Trie树+主席树)
- 【BZOJ 3439】Kpm的MC密码 主席树+trie树
- 【BZOJ 3439】Kpm的MC密码 主席树+trie树
- 3439: Kpm的MC密码 trie+主席树
- BZOJ3439: Kpm的MC密码
- BZOJ3439 KPM的MC密码
- BZOJ3439: Kpm的MC密码
- bzoj3439: Kpm的MC密码
- [BZOJ]3439: Kpm的MC密码 trie树+主席树(线段树合并)
- bzoj3439: Kpm的MC密码(四种做法)
- BZOJ 3439 Kpm的MC密码 Trie树+可持久化线段树
- BZOJ 3439 Kpm的MC密码 Trie+可持久化线段树
- [BZOJ 3439]Kpm的MC密码
- bzoj 3439: Kpm的MC密码
- bzoj 3439: Kpm的MC密码
- 也谈谈百度
- 用C++语言写游戏——打怪小游戏
- java回调函数
- Android自定义Toast的时长、位置、及显示的View
- 杂谈嵌入式linux和单片机开发
- 【BZOJ3439】Kpm的MC密码,trie树+dfs序+主席树
- centos 7 安装无线网卡rtl8188EUS_rtl8189ES驱动
- iOS APP提交上架最新流程
- Android之SurfaceView简介(一)
- HDU 5112 A Curious Matt
- 最新python中一升级所有已安装的包方法
- POJ 2431 Expedition
- Percona Xtrabackup myql 快速备份与恢复
- HDU 5113 Black And White(搜索+剪枝)