BZOJ 1014: [JSOI2008]火星人prefix
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1014: [JSOI2008]火星人prefix相关的知识,希望对你有一定的参考价值。
Sol
Splay+Hash+二分答案.
用Splay维护Hash,二分答案判断.
复杂度 \(O(nlog^2n)\)
PS:这题调了两个晚上因为没开long long.许久不写数据结构题感觉写完整个人都不好了...
感觉还是应该经常开几道数据结构题来毒自己.
Code
/************************************************************** Problem: 1014 User: BeiYu Language: C++ Result: Accepted Time:6580 ms Memory:9320 kb ****************************************************************/ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; typedef unsigned long long LL; const int N = 200050; #define lc(o) d[o].ch[0] #define rc(o) d[o].ch[1] #define f(o) d[o].f #define h(o) d[o].h #define v(o) d[o].v #define s(o) d[o].s #define mid ((l+r)>>1) //char *ps=(char *)malloc(N<<3); inline int in(int x=0,char ch=getchar()){ while(ch>‘9‘||ch<‘0‘) ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x; } LL p[N];char ch[N]; struct SplayTree{ struct Node{ int ch[2],f; LL h,v;int s; void Init(LL hh,LL vv,int ss){ h=hh,v=vv,s=ss,ch[0]=ch[1]=f=0; } }d[N]; int rt,cnt; void PushUp(int o){ if(!o) return; d[o].h=0;d[o].s=d[lc(o)].s+d[rc(o)].s+1; h(o)=(LL)h(lc(o))+v(o)*p[s(lc(o))]+h(rc(o))*p[s(lc(o))+1]; // if(rc(o)!=0) h(o)=h(o)+h(rc(o)); // h(o)=h(o)+v(o)*p[d[rc(o)].s]; // if(lc(o)!=0) h(o)=h(o)+h(lc(o))*p[d[rc(o)].s+1]; } void Build(int &o,int fa,int l,int r){ if(l>r) return; o=++cnt; d[o].Init(0,0,0); if(ch[mid]>=‘a‘) d[o].v=ch[mid]-‘a‘+13; f(o)=fa; Build(lc(o),o,l,mid-1); Build(rc(o),o,mid+1,r); PushUp(o); } // int Build(int l,int r,int fa){ // if(l==r){ // d[l].Init(0,0,0); // if(ch[l]>=‘a‘) d[l].v=d[l].h=ch[l]-‘a‘+1; // d[l].s=1,f(l)=fa,PushUp(l);return l; // } // d[mid].Init(0,0,0); // if(ch[mid]>=‘a‘) v(mid)=ch[mid]-‘a‘+1;f(mid)=fa; // if(l<mid) lc(mid)=Build(l,mid-1,mid); // if(r>mid) rc(mid)=Build(mid+1,r,mid); // PushUp(mid);return mid; // } void Rot(int o){ int p=f(o),k=f(p),r=rc(p)==o; if(k) d[k].ch[rc(k)==p]=o; d[d[o].ch[r^1]].f=p,d[o].f=k; d[p].ch[r]=d[o].ch[r^1],d[o].ch[r^1]=p,d[p].f=o; PushUp(p),PushUp(o); } void DFS(int o){ if(lc(o)) DFS(lc(o)); cout<<o<<" "<<d[o].v<<" "<<d[o].h<<" "<<d[o].s<<endl; cout<<" lc="<<lc(o)<<" rc="<<rc(o)<<" f="<<f(o)<<endl; if(rc(o)) DFS(rc(o)); } void Splay(int o,int g){ for(;f(o)!=g;){ int p=f(o),k=f(p); if(k!=g) Rot((rc(p)==o)==(rc(k)==p)?p:o); // cout<<"Ok Rot"<<endl; Rot(o); }if(!g) rt=o; // cout<<"rt="<<rt<<endl; // DFS(rt); } int findkth(int o,int k){ if(d[lc(o)].s>=k) return findkth(lc(o),k); else if(d[lc(o)].s+1<k) return findkth(rc(o),k-d[lc(o)].s-1); else return o; } void Insert(int x,LL v){ int p=findkth(rt,x),q=findkth(rt,x+1); Splay(p,0),Splay(q,p); // d[++cnt].Init(0,v,0);rt=cnt; // rc(p)=0,f(p)=f(q)=rt,lc(rt)=p,rc(rt)=q; // PushUp(p),PushUp(q),PushUp(rt); d[++cnt].Init(0,v,0); f(cnt)=q,lc(q)=cnt; PushUp(cnt),PushUp(q),PushUp(p); } void Change(int x,LL v){ int o=findkth(rt,x); Splay(o,0),d[o].v=v,PushUp(o); } void init(){ // fread(ps,1,N<<3,stdin); p[0]=1;for(int i=1;i<N;i++) p[i]=(LL)p[i-1]*197; d[0].Init(0,0,0); scanf("%s",ch+2);int n=strlen(ch+2); Build(rt,0,1,n+2); // rt=Build(1,n+2,0); // cout<<rt<<" "<<cnt<<endl; } LL Query(int u,int v){ // if(u>v) return -1; u--,v++; u=findkth(rt,u),v=findkth(rt,v); // cout<<"Ok find "<<u<<" "<<v<<endl; Splay(u,0),Splay(v,u); // cout<<"Ok Splay"<<endl; return h(lc(v)); } void sol(){ char opt[5],c[5];int u,v; for(int m=in();m--;){ scanf("%s",opt); // cout<<opt<<"********"<<endl; if(opt[0]==‘R‘) scanf("%d%s",&u,c),Change(u+1,c[0]-‘a‘+13); else if(opt[0]==‘I‘) scanf("%d%s",&u,c),Insert(u+1,c[0]-‘a‘+13); else { u=in()+1,v=in()+1; int l=0,r=min(cnt-v,cnt-u); // cout<<"Start Q"<<endl<<"*********"<<endl; while(l<=r){ // cout<<"***\ncs mid="<<mid<<endl; // cout<<u<<" "<<mid<<" "<<Query(u,u+mid-1)<<endl; // cout<<v<<" "<<mid<<" "<<Query(v,v+mid-1)<<endl; if((LL)Query(u,u+mid-1)==Query(v,v+mid-1)) l=mid+1; else r=mid-1; }printf("%d\n",r); } // cout<<opt<<" is ok"<<endl; } } }spl; int main(){ // freopen("in.in","r",stdin); // freopen("out.out","w",stdout); spl.init(); // cout<<"Finish init()"<<endl; // spl.DFS(spl.rt); // cout<<"Finish DFS()"<<endl; spl.sol(); // cout<<"Finish sol()"<<endl; return 0; }
以上是关于BZOJ 1014: [JSOI2008]火星人prefix的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)
[BZOJ1014][JSOI2008]火星人prefix splay+二分+hash
[BZOJ]1014 火星人prefix(JSOI2008)