當(dāng)前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
P4036-[JSOI2008]火星人【Splay,二分,hash】
生活随笔
收集整理的這篇文章主要介紹了
P4036-[JSOI2008]火星人【Splay,二分,hash】
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P4036
題目大意
一個(gè)字符串要求支持
解題思路
如果不考慮修改我們可以用二分+hash+hash+hash解決該問題,但是涉及到修改和插入我們考慮用SplaySplaySplay維護(hù)hashhashhash值。
合并時(shí)使用hash=hashl?psizr+1+val?psizr+hashrhash=hash_l*p^{siz_r+1}+val*p^{siz_r}+hash_rhash=hashl??psizr?+1+val?psizr?+hashr?進(jìn)行合并即可。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define ull unsigned long long using namespace std; const int N=2e5+10; const ull base=131; struct node{int siz;ull val,hash; }a[N]; int n,root,tot,m; int t[N][2],fa[N]; char s[N]; ull p[N]; bool Direct(int x) {return t[fa[x]][1]==x;} void Merge(int x){a[x].siz=a[t[x][0]].siz+a[t[x][1]].siz+1;a[x].hash=p[a[t[x][1]].siz+1]*a[t[x][0]].hash+p[a[t[x][1]].siz]*a[x].val+a[t[x][1]].hash; } void Connect(int x,int y,int dir) {t[x][dir]=y;fa[y]=x;} void Rotate(int x){int y=fa[x],root=fa[fa[x]];int ys=Direct(x),rs=Direct(y);int z=t[x][ys^1];Connect(y,z,ys);Connect(x,y,ys^1);Connect(root,x,rs);Merge(y);Merge(x);return; } void Splay(int x,int f) {while(fa[x]!=f){int up=fa[x];if(fa[up]==f) Rotate(x);else if(Direct(x)==Direct(up))Rotate(up),Rotate(x);else Rotate(x),Rotate(x); }return; } int Find(int x,int k) {if(a[t[x][0]].siz>=k) return Find(t[x][0],k);if(a[t[x][0]].siz+1==k) return x;return Find(t[x][1],k-a[t[x][0]].siz-1); } int Split(int l,int r) {int x=Find(root,l),y=Find(root,r+2);Splay(x,0);Splay(y,x);root=x;return t[y][0]; } ull ValSeq(int x,int y) {return a[Split(x,y)].hash; } int main() {scanf("%s",s+1);n=strlen(s+1);a[1].siz=p[0]=1;for(int i=1;i<N;i++)p[i]=p[i-1]*base;for(int i=1;i<=n;i++){a[i+1].val=s[i]-'a'+1;fa[i]=i+1;t[i+1][0]=i;Merge(i+1);}fa[n+1]=n+2;t[n+2][0]=n+1;Merge(n+2);root=tot=n+2;scanf("%d",&m);while(m--){char op[2];scanf("%s",op);if(op[0]=='Q'){int x,y;scanf("%d%d",&x,&y);int l=0,r=min(n-x,n-y);while(l<=r){int mid=(l+r)/2;if(ValSeq(x,x+mid)==ValSeq(y,y+mid)) l=mid+1;else r=mid-1;}printf("%d\n",r+1);}if(op[0]=='R'){int x;char c[2];scanf("%d%s",&x,c);int k=Split(x,x);a[k].val=a[k].hash=c[0]-'a'+1;Splay(k,0);root=k;}if(op[0]=='I'){int x;char c[2];scanf("%d%s",&x,c);x++;int l=Find(root,x),r=Find(root,x+1);Splay(l,0);Splay(r,l);n++;fa[++tot]=r;t[r][0]=tot;a[tot].siz=1;a[tot].val=a[tot].hash=c[0]-'a'+1;Splay(tot,0);root=tot;}} }總結(jié)
以上是生活随笔為你收集整理的P4036-[JSOI2008]火星人【Splay,二分,hash】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 长期面对电脑应该如何护肤经常用电脑如何护
- 下一篇: 最简单的方法教你电脑硬盘怎么分区如何将电