【BZOJ 1014】[JSOI2008]火星人prefix hash+splay+二分
来源:互联网 发布:轻而易举的软件多少钱 编辑:程序博客网 时间:2024/04/30 02:00
一开始以为会是后缀数组之类的什么鬼东西,结果最后想了半天没想出来,结果想到hash秒出答案,所以有的时候应该考虑换一下思维方式。
因为题目要求查询和修改操作,维护一个splay,每个节点对应这个位置的字符和这棵子树的hash值,就能完成插入修改操作了,每一个询问的时候再二分最长前缀hash cheak就好了
然后。。。有一个函数忘了写return值结果BZOJ一直说我T,我改了很多常数还是T,最后才发现就过了郁闷
#include<cstdio>#include<cstring>#include<iostream>#define maxn 200020#define ls ch[u][0]#define rs ch[u][1]#define uint unsigned intusing namespace std;int ch[maxn][2],val[maxn],fa[maxn],size[maxn],rt,tot,len;uint pw[maxn],h[maxn]; void init(int u){ size[u]=size[ls]+size[rs]+1; h[u]=(h[ls]*pw[size[rs]+1]+val[u]*pw[size[rs]]+h[rs]);}void Rotate(int u){ int d=u==ch[fa[u]][0]; int f=fa[u],ff=fa[f]; fa[u]=ff;if(ff!=0)ch[ff][f==ch[ff][1]]=u; ch[f][!d]=ch[u][d];fa[ch[u][d]]=f; ch[u][d]=f;fa[f]=u; init(f);init(u);}void splay(int u,int k=0){ if(u==0)return; while(fa[u]!=k){ int f=fa[u],ff=fa[f]; if(ff==k){Rotate(u);break;} int d=u==ch[f][1],dd=f==ch[ff][1]; if(d==dd)Rotate(f); else Rotate(u); Rotate(u); } if(k==0)rt=u;}//插入一个符号是x 排在第k的字符 void insert(int u,int f,int x,int k,int d){ if(u==0){ tot++; val[tot]=h[tot]=x,fa[tot]=f,size[tot]=1,ch[f][d]=tot; splay(tot); return; } if(k>size[ls]+1)insert(rs,u,x,k-size[ls]-1,1); else insert(ls,u,x,k,0);}void change(int u,int k,int x){ if(k==size[ls]+1){ splay(u);val[u]=x; init(u); return; } if(k>size[ls]+1)change(rs,k-size[ls]-1,x); else change(ls,k,x);}//找k的前缀和 uint query(int u,int k){ if(k==0)return 0; if(k==size[ls]+1){ splay(u); return h[ls]*pw[1]+val[u]; } if(k>size[ls]+1)return query(rs,k-size[ls]-1); return query(ls,k);}uint find(int a,int b){ if(b==0)return 0; if(a+b-1>len)return -a; return query(rt,a+b-1)-query(rt,a-1)*pw[b];} int solve(int a,int b){ int l=0,r=min(len-a,len-b)+1,ans; while(l<=r){ int mid=l+r>>1; if(find(a,mid)==find(b,mid))ans=mid,l=mid+1; else r=mid-1; } return ans;}char s[maxn],c[5];int build(int l,int r,int f){ if(l>r)return 0; tot++; int u=tot; if(l==r){ h[u]=val[u]=s[l]-'a',fa[u]=f,size[u]=1; return u; } int mid=l+r>>1; val[u]=s[mid]-'a',fa[u]=f; ch[u][0]=build(l,mid-1,u); ch[u][1]=build(mid+1,r,u); init(u); return u;} int main(){ pw[0]=1; for(int i=1;i<=200000;i++)pw[i]=pw[i-1]*233; scanf("%s",s+1);len=strlen(s+1);int a,b,n; rt=build(1,len,0); scanf("%d",&n); while(n--){ scanf("%s",c); if(c[0]=='Q'){ scanf("%d%d",&a,&b); printf("%d\n",solve(a,b)); }else if(c[0]=='R'){ scanf("%d%s",&a,c); change(rt,a,c[0]-'a'); }else { scanf("%d%s",&a,c); insert(rt,0,c[0]-'a',a+1,a+1>size[ch[rt][0]]+1); len++; } } return 0;}
0 0
- BZOJ 1014 JSOI2008 火星人prefix Splay+Hash+二分
- BZOJ 1014 JSOI2008 火星人prefix Splay+Hash+二分
- 【BZOJ 1014】[JSOI2008]火星人prefix hash+splay+二分
- 【bzoj1014】[JSOI2008]火星人prefix splay+hash+二分
- bzoj 1014: [JSOI2008]火星人prefix (hash+splay)
- bzoj 1014: [JSOI2008]火星人prefix(splay维护区间+Hash+二分)
- 【splay】BZOJ 1014: [JSOI2008]火星人prefix
- bzoj 1014 [JSOI2008]火星人prefix 哈希+splay
- BZOJ 1014 火星人 prefix (splay hash 二分答案)
- [BZOJ1014] [JSOI2008] 火星人prefix - splay + hash + 二分答案
- 【bzoj1014】【jsoi2008】【火星人prefix】【splay+hash】
- 【BZOJ1014】[JSOI2008]火星人prefix【Splay】【Hash】
- bzoj1014 [JSOI2008]火星人prefix ( splay + hash )
- [splay+二分+哈希] BZOJ1014: [JSOI2008]火星人prefix
- BZOJ 1014: [JSOI2008]火星人prefix
- 【BZOJ 1014】 [JSOI2008]火星人prefix
- 【 bzoj 1014 】 [JSOI2008]火星人prefix
- BZOJ 1014 [JSOI2008]火星人prefix
- SPI通信学习
- [Mapbox GL]使用按钮修改layer的颜色
- keepalived实现Tomcat服务双机热备
- jdk与jre的区别
- oracle 网络访问配置tnsnames.ora文件的路径
- 【BZOJ 1014】[JSOI2008]火星人prefix hash+splay+二分
- Linux下安装、配置、启动Apache
- CF#386(Div.2) 解题报告
- 機器人學總結(4) —— 逆運動學
- CI框架教程3——实现框架前后端分离
- nginx + tomcat 负载均衡
- zookeeper 操作 顺序性如何保证
- gulp的安装教程,使用教程,和简单的自动化任务教程
- 【数据库】使用PLSQL工具时,ORACLE客户端连接串的配置