bzoj3467: Crash和陶陶的游戏

时间:2022-07-29 03:01:31

就一篇题解:

BZOJ3467 : Crash和陶陶的游戏 - weixin_34248487的博客 - CSDN博客

1.离线,建出Atrie树;B树的倍增哈希数组,节点按照到根路径字典序排序

2.处理A节点对应前缀对应B中的极长可以匹配的区间。在父亲节点区间内二分即可

3.更新答案:

①加入A点,找区间中B中已经出现点个数。树状数组

②加入B点,本质是B到根的字符串放在trie最大匹配长度,二分,哈希表存A树是否有这个前缀,得到的长度就是当前匹配长度。

直上直下的链本质是字符串的前缀后缀。

动态更新hash很难,就离线,在可能贡献的集合内找到当前出现的。

假装有代码.jpg

这个是两个logn的

可以变成一个logn!

sort是不必要的,

对于②B树点对trie的影响,不妨直接倍增+hash找到最长的匹配位置y,在y的位置++,然后①时候子树查询即可!

通过提前打好标记使得不用同时考虑很多!

(类似预处理)

还有可能一个点有多个c儿子,要合并成一个。①的时候整个子树++,表示到根的路径上多了一个点,②的时候,匹配最长位置单点查询这个值

两个树状数组

注意,unsigned long long哈希

单模数随便rand就卡掉了

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
#define ul unsigned long long
#define ll unsigned long long
using namespace std;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');} namespace Miracle{
const int N=2e5+;
const ul base=;
const int orz=; struct HA{
int nxt[N],hd[N],cnt;
ul val[N];
int id[N];
void ins(int x,ll h){
int pos=h%orz;
nxt[++cnt]=hd[pos];hd[pos]=cnt;val[cnt]=h;
id[cnt]=x;
}
int query(ll h){
int pos=h%orz;
for(reg i=hd[pos];i;i=nxt[i]){
if(val[i]==h) return id[i];
}
return -;
}
}ha;
//trie
int ch[N][];
int id[N];//is
int n;
int tot;
int lp;
ul pw[(<<)+];
void ins(int x,int c){
++lp;
x=id[x];
// cout<<" true fa "<<x<<" ch "<<ch[x][c]<<endl;
if(ch[x][c]){
id[lp]=ch[x][c];return;
}
id[lp]=++tot;
ch[x][c]=tot;
}
int dfn[N],df,dfn2[N];
void fin(int x,ul haxi,int d){
dfn[x]=++df;
if(x!=){
ha.ins(x,haxi);
}
for(reg i=;i<;++i){
if(ch[x][i]){
fin(ch[x][i],haxi+(ll)pw[d]*(i+),d+);
}
}
dfn2[x]=df;
}
//B tree
int cur;
struct node{
int nxt,to;
int val;
}e[*N];
int hd[N],cnt;
void add(int x,int y,int z){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
e[cnt].val=z;
hd[x]=cnt;
}
int fa[N][];
ul hsh[N][];
void dfs(int x){
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
fa[y][]=x;
hsh[y][]=e[i].val+;
dfs(y);
}
}
//question
struct que{
int typ,fa,c;
int x;
}q[N]; int get(int x){
ll now=;
int has=;
int ret=;
for(reg j=;j>=;--j){
if(!fa[x][j]) continue;
ll tmp=((ll)now+pw[has]*hsh[x][j]);
int nc=ha.query(tmp);
if(nc!=-){
ret=nc;
now=tmp;
has+=(<<j);
x=fa[x][j];//shit
}
}
return ret;
} struct treearray{
int f[N];
int n;
void upda(int x,int c){
for(;x<=n;x+=x&(-x)) f[x]+=c;
}
int query(int x){
int ret=;
for(;x;x-=x&(-x)) ret+=f[x];return ret;
}
}t1,t2;
int main(){
rd(n);
char s[];
++tot;++cur;//start
lp=;
id[]=; ll ans=;
ans=;//1 1
for(reg i=;i<=n;++i){
rd(q[i].typ);rd(q[i].fa);//rd(q[i].c);
scanf("%s",s+);q[i].c=s[]-'a';
if(q[i].typ==){
ins(q[i].fa,q[i].c);
q[i].x=id[lp];
// prt(id,1,lp);
}else{
++cur;
q[i].x=cur;
add(q[i].fa,cur,q[i].c);
}
// cout<<tot<<" ";
}
// cout<<endl<<endl;
dfs();
// cout<<"after dfs "<<tot<<endl;
// prt(id,1,lp); pw[]=;
for(reg i=;i<=(<<);++i){
pw[i]=(ll)pw[i-]*base;//%mod;
}
for(reg j=;j<=;++j){
for(reg i=;i<=cur;++i){
fa[i][j]=fa[fa[i][j-]][j-];
hsh[i][j]=((ll)hsh[i][j-]+(ll)hsh[fa[i][j-]][j-]*pw[<<(j-)]);//%mod)%mod;
}
}
// cout<<"after bezeng "<<endl;
fin(,,);
// cout<<" after fin "<<endl;
t1.n=t2.n=tot;
// cout<<" tot "<<tot<<endl;
// prt(dfn,1,tot);
// cout<<" dfn2-------------------------- "<<endl;
// prt(dfn2,1,tot);
int tc=,tb=;
for(reg i=;i<=n;++i){
if(q[i].typ==){//add trie
++tc;
// cout<<"trie "<<endl;
int x=q[i].x;//ch[id[q[i].fa]][q[i].c];
// cout<<"x "<<x<<" tc "<<tc<<endl;
ans+=t1.query(dfn2[x])-t1.query(dfn[x]-);
t2.upda(dfn[x],);t2.upda(dfn2[x]+,-);
}else{//add B tree
++tb;
// cout<<" Btree "<<endl;
// cout<<" x "<<q[i].x<<endl;
int y=get(q[i].x);
// cout<<" y "<<y<<" tb "<<tb<<" dfn "<<dfn[y]<<endl;
if(y){
ans+=t2.query(dfn[y]);
t1.upda(dfn[y],);
}
++ans;
}
printf("%lld\n",ans);
}
return ;
} }
signed main(){
// freopen("5.in","r",stdin);
// freopen("my.out","w",stdout);
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2019/3/26 18:56:24
*/

bzoj3467: Crash和陶陶的游戏的更多相关文章

  1. P1676陶陶吃苹果 - vijos

    描述 curimit知道陶陶很喜欢吃苹果.于是curimit准备在陶陶生日的时候送给他一棵苹果树. curimit准备了一棵这样的苹果树作为生日礼物:这棵苹果树有n个节点,每个节点上有c[i]个苹果, ...

  2. bzoj 2402&colon; 陶陶的难题II 二分答案维护凸包

    2402: 陶陶的难题II Time Limit: 40 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 68  Solved: 45[Submi ...

  3. bzoj 2401&colon; 陶陶的难题I 数论

    2401: 陶陶的难题I Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 89  Solved: 24[Submit][Status] Descript ...

  4. 武汉科技大学ACM:1007&colon; 陶陶摘苹果

    Problem Description 厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试. 个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高度,请帮陶陶算一下她能够摘到的苹 ...

  5. 洛谷-陶陶摘苹果(升级版)-BOSS战-入门综合练习1

    题目描述 Description 又是一年秋季时,陶陶家的苹果树结了n个果子.陶陶又跑去摘苹果,这次她有一个a公分的椅子.当他手够不着时,他会站到椅子上再试试. 这次与NOIp2005普及组第一题不同 ...

  6. NOIP2005-普及组复赛-第一题-陶陶摘苹果

    题目描述 Description 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳 ...

  7. noip普及组2005 陶陶摘苹果

    陶陶摘苹果 描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试. 现在 ...

  8. 2719&colon;陶陶摘苹果-poj

    2719:陶陶摘苹果 总时间限制:  1000ms 内存限制:  65536kB 描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米 ...

  9. &lbrack;Vijos 1676&rsqb; 陶陶吃苹果

    Description curimit知道陶陶很喜欢吃苹果.于是curimit准备在陶陶生日的时候送给他一棵苹果树. curimit准备了一棵这样的苹果树作为生日礼物:这棵苹果树有n个节点,每个节点上 ...

随机推荐

  1. 随机函数的代码(srand、rand)

    #include<stdio.h> int main() int counter; for(counter=0;counter<10;counter++) { srand(count ...

  2. JavaScript学习笔记-new Date&lpar;&rpar; 与 Date&lpar;&rpar; 的区别

    var today1 = Date() //返回一个字符串(string),没有getDate等日期对象方法,内容为当前时间 var today2 = new Date() //返回一日期对象,内容为 ...

  3. ubuntu下交叉编译windows c程序

    简介 采用mingw32可以在linux下直接编译c程序输出为windows下的exe程序或dll链接库. 个人编译的纯c程序(不含winapi),主要是c99程序,通常采用gcc/cc编译调试后,再 ...

  4. 王家林 大数据Spark超经典视频链接全集&lbrack;转&rsqb;

    压缩过的大数据Spark蘑菇云行动前置课程视频百度云分享链接 链接:http://pan.baidu.com/s/1cFqjQu SCALA专辑 Scala深入浅出经典视频 链接:http://pan ...

  5. CGI实现页面的动态生成

    传统的Web应用开发局限于有限的静态页面(HTML静态页面),不利于系统的扩展,不能提供及时信息,而且修改维护麻烦,所以建立一个动态Web应用程序尤为重要.一方面根据访问者的不同请求返回不同的访问信息 ...

  6. Java虚拟机学习 - 对象访问

    对象访问会涉及到Java栈.Java堆.方法区这三个内存区域. 如下面这句代码: Object objectRef = new Object(); 假设这句代码出现在方法体中,"Object ...

  7. c&num;md5与SHA1验证函数

    /// <summary> /// MD5验证函数 /// </summary> /// <param name="fileName">文件的路 ...

  8. C&plus;&plus; 顶层 const

    我的主力博客:半亩方塘 本文的主要參考来源来自于:C++ Primer 中文版(第 5 版) 第 57 面至第 58 面 1. 顶层 const 与底层 const 概念 我们知道,指针本身是一个对象 ...

  9. oracle整体知识的大致介绍&lpar;1&rpar;-概念

    表空间: oracle允许不同类型的数据分开存放,表空间是数据库的逻辑划分. 数据文件: 表空间由同一磁盘上的一个或多个文件组成,这些文件叫做数据文件. 实例: 是存放和控制数据库的软件机制. ora ...

  10. HTML DOCTYPE 重要性

    定义和使用方法 <!DOCTYPE> 声明必须是 HTML 文档的第一行.位于 <html> 标签之前. <!DOCTYPE> 声明不是 HTML 标签.它是指示 ...