【BZOJ1014】火星人
splay+hash,splay维护区间hash值,查询的时候二分答案。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long LL;
using namespace std;
const int maxn=100010,p1=1000007,p2=1000009;
inline void readchar(char &ch) {while ((ch=getchar())==' ' || ch=='\n');}
inline void read(int &x) {char ch;while ((ch=getchar())<'0' || ch>'9');x=ch-'0';while ((ch=getchar())<='9' && ch>='0') x=x*10+ch-'0';}
char s[maxn];
int n;
struct Node
{
Node *p,*c[2];
int v,size,h1,h2;
bool w() {return p->c[1]==this;}
}*root,*Null;
namespace Memory
{
Node Mem[maxn],*Stack[maxn];
int top;
void Init() {for (int i=0;i<maxn;i++) Stack[i]=Mem+i;top=maxn;}
Node* New_Node() {return Stack[--top];}
void Delete_Node(Node *x) {Stack[top++]=x;}
}
int h1[maxn],h2[maxn];
struct Splay_Tree
{
#define ls x->c[0]
#define rs x->c[1]
void Update(Node *x)
{
if (x==Null) return;
x->size=ls->size+rs->size+1;
x->h1=(ls->h1+1ll*x->v*h1[ls->size]+1ll*rs->h1*h1[ls->size+1])%p1;
x->h2=(ls->h2+1ll*x->v*h2[ls->size]+1ll*rs->h2*h2[ls->size+1])%p2;
}
void Rotate(Node *x)
{
Node *p=x->p;
bool w=x->w();
x->c[!w]->p=p;p->p->c[p->w()]=x;
p->c[w]=x->c[!w];x->c[!w]=p;
x->p=p->p;p->p=x;
Update(p);
if (p==root) root=x;
}
void Splay(Node *x,Node *head)
{
while (x->p!=head)
{
if (x->p->p==head) Rotate(x);
else if (x->w()==x->p->w()) Rotate(x->p),Rotate(x);
else Rotate(x),Rotate(x);
}
Update(x);
}
Node* Select(int kth)
{
Node *x=root;
while (kth)
{
int lsize=ls->size;
if (lsize+1==kth) return x;
if (lsize<kth) kth-=lsize+1,x=rs;
else x=ls;
}
return x;
}
Node* Get_Seq(int l,int r)
{
if (l==1 && r==n) return root;
if (l==1) {Splay(Select(r+1),Null);return root->c[0];}
if (r==n) {Splay(Select(l-1),Null);return root->c[1];}
Splay(Select(l-1),Null);
Splay(Select(r+1),root);
return root->c[1]->c[0];
}
Node* New_Node(int v)
{
Node *x=Memory::New_Node();
x->v=v;x->size=1;
x->h1=x->h2=v;
x->p=ls=rs=Null;
return x;
}
Splay_Tree()
{
Memory::Init();
Null=Memory::New_Node();
Null->v=Null->size=Null->h1=Null->h2=0;
Null->p=Null=Null->c[0]=Null->c[1]=Null;
root=Null;
}
void Insert(int pos,int v)
{
Node *x=New_Node(v);
if (pos==0)
{
Splay(Select(1),Null);
root->c[0]=x;
x->p=root;
Update(root);
}
else if (pos==n)
{
Splay(Select(n),Null);
root->c[1]=x;
x->p=root;
Update(root);
}
else
{
Splay(Select(pos),Null);
Splay(Select(pos+1),root);
root->c[1]->c[0]=x;
x->p=root->c[1];
Splay(x,Null);
}
}
void Change(int pos,int v)
{
Node *x=Select(pos);
x->v=v;
Splay(x,Null);
}
Node* Make_Tree(int l,int r)
{
if (l>r) return Null;
int mid=(l+r)>>1;
Node *x=New_Node((int)s[mid]);
ls=Make_Tree(l,mid-1);
rs=Make_Tree(mid+1,r);
if (ls!=Null) ls->p=x;
if (rs!=Null) rs->p=x;
Update(x);
return x;
}
LL Hash_Val(int pos,int tot)
{
LL res=0;
Node *x=Get_Seq(pos,pos+tot-1);
res=x->h1*(LL)p2+x->h2;
return res;
}
}T;
int main()
{
h1[0]=h2[0]=1;
for (int i=1;i<maxn;i++) h1[i]=(h1[i-1]*257)%p1,h2[i]=(h2[i-1]*259)%p2;
scanf("%s",s);
n=strlen(s);
root=T.Make_Tree(0,n-1);
root->p=Null;
int m;
read(m);
while (m--)
{
char ctr;
readchar(ctr);
if (ctr=='Q')
{
int x,y;
read(x),read(y);
int l=0,r=min(n+1-x,n+1-y),mid;
while (l<r)
{
mid=(l+r+1)>>1;
if (T.Hash_Val(x,mid)!=T.Hash_Val(y,mid)) r=mid-1;
else l=mid;
}
printf("%d\n",l);
}
else if (ctr=='I')
{
int x;char ch;
read(x);readchar(ch);
T.Insert(x,(int)ch);
n++;
}
else
{
int x;char ch;
read(x);readchar(ch);
T.Change(x,ch);
}
}
return 0;
}
评论 (0)