1014: [JSOI2008]火星人prefix

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2918  Solved: 866
[Submit][Status]

Description

火星人最近研究了一种操作:求一个字串两个后缀的公共前缀。比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串,两个字串的公共前缀的长度。比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4, 7) = 0 在研究LCQ函数的过程中,火星人发现了这样的一个关联:如果把该字符串的所有后缀排好序,就可以很快地求出LCQ函数的值;同样,如果求出了LCQ函数的值,也可以很快地将该字符串的后缀排好序。 尽管火星人聪明地找到了求取LCQ函数的快速算法,但不甘心认输的地球人又给火星人出了个难题:在求取LCQ函数的同时,还可以改变字符串本身。具体地说,可以更改字符串中某一个字符的值,也可以在字符串中的某一个位置插入一个字符。地球人想考验一下,在如此复杂的问题中,火星人是否还能够做到很快地求取LCQ函数的值。

Input

第一行给出初始的字符串。第二行是一个非负整数M,表示操作的个数。接下来的M行,每行描述一个操作。操作有3种,如下所示: 1、 询问。语法:Q x y,x, y均为正整数。功能:计算LCQ(x, y) 限制:1 <= x, y <= 当前字符串长度。 2、 修改。语法:R x d,x是正整数,d是字符。功能:将字符串中第x个数修改为字符d。限制:x不超过当前字符串长度。 3、 插入:语法:I x d,x是非负整数,d是字符。功能:在字符串第x个字符之后插入字符d,如果x = 0,则在字符串开头插入。限制:x不超过当前字符串长度。

Output

对于输入文件中每一个询问操作,你都应该输出对应的答案。一个答案一行。

Sample Input

madamimadam
7
Q 1 7
Q 4 8
Q 10 11
R 3 a
Q 1 7
I 10 a
Q 2 11

Sample Output

5
1
0
2
1
数据规模:
对于100%的数据,满足:
1、 所有字符串自始至终都只有小写字母构成。
2、 M <= 150,000
3、 字符串长度L自始至终都满足L <= 100,000
4、 询问操作的个数不超过10,000个。

对于第1,2个数据,字符串长度自始至终都不超过1,000
对于第3,4,5个数据,没有插入操作。

HINT

 

Source

题解:

以前看着这题好麻烦,什么都不会的说。。。

现在看起来用splay似乎是显然的。。。

还是吐槽:

1.第一遍打错了好几个关键的地方竟然还能得70分。。。

2.为什么我的splay总是这么慢。。。

代码:

1.mine  光荣的TLE,不过在tyvj上AC的

 const maxn=+;
p=;
var i,n,m,x,t,y,z,l,r,rt,mid,tot:longint;
ch:char;
st:ansistring;
s,v,w,fa,a:array[..maxn] of int64;
c:array[..maxn,..] of longint;
procedure pushup(x:longint);
begin
s[x]:=s[c[x,]]+s[c[x,]]+;
w[x]:=(w[c[x,]]*a[s[c[x,]]+] mod p+
v[x]*a[s[c[x,]]] mod p
+w[c[x,]] mod p) mod p;
end;
procedure rotate(x:longint;var k:longint);
var l,r,y,z:longint;
begin
y:=fa[x];z:=fa[y];
l:=ord(c[y,]=x);r:=l xor ;
if y=k then k:=x else c[z,ord(c[z,]=y)]:=x;
fa[x]:=z;fa[y]:=x;fa[c[x,r]]:=y;
c[y,l]:=c[x,r];c[x,r]:=y;
pushup(y);pushup(x);
end;
procedure splay(x:longint;var k:longint);
var y,z:longint;
begin
while x<>k do
begin
y:=fa[x];z:=fa[y];
if y<>k then
if (c[z,]=y) xor (c[y,]=x) then rotate(x,k)
else rotate(y,k);
rotate(x,k);
end;
end;
function find(x,rank:longint):longint;
var l,r:longint;
begin
l:=c[x,];r:=c[x,];
if s[l]+=rank then exit(x)
else if s[l]>=rank then exit(find(l,rank))
else exit(find(r,rank-s[l]-));
end;
procedure del(k:longint);
var x,y,z:longint;
begin
x:=find(rt,k-);y:=find(rt,k+);
splay(x,rt);splay(y,c[x,]);
z:=c[y,];fa[z]:=;s[z]:=;c[y,]:=;
pushup(y);pushup(x);
end; procedure build(l,r,f:longint);
var mid,now,last:longint;
begin
if l>r then exit;
mid:=(l+r)>>;
now:=mid;last:=f;
fa[now]:=last;
c[last,ord(mid>f)]:=now;
if l=r then
begin
s[now]:=;w[now]:=v[now];
exit;
end;
build(l,mid-,mid);build(mid+,r,mid);
pushup(now);
end; procedure init;
begin
a[]:=;
for i:= to maxn do a[i]:=(a[i-]*) mod p;
readln(st);n:=length(st);
for i:= to n+ do v[i]:=ord(st[i-])-ord('a')+;
build(,n+,);rt:=(n+)>>;
end;
function check(l,r,len:longint):boolean;
var x,y,xx,yy:longint;
begin
if len= then exit(true);
x:=find(rt,l);y:=find(rt,l+len+);
splay(x,rt);splay(y,c[x,]);
xx:=w[c[y,]];
x:=find(rt,r);y:=find(rt,r+len+);
splay(x,rt);splay(y,c[x,]);
yy:=w[c[y,]];
if xx=yy then exit(true) else exit(false);
end;
function query(x,y:longint):longint;
var l,r,mid:longint;
begin
if x>y then begin t:=x;x:=y;y:=t;end;
if x=y then exit(tot-y-);
if not(check(x,y,)) then exit();
if check(x,y,tot-y-) then exit(tot-y-);
l:=;r:=tot-y-;
while l<r do
begin
mid:=(l+r)>>;
if check(x,y,mid) then l:=mid+ else r:=mid;
end;
exit(l-);
end;
procedure main;
begin
readln(m);tot:=n+;
for i:= to m do
begin
read(ch);
case ch of
'R':begin
read(x);read(ch);readln(ch);
x:=find(rt,x+);
splay(x,rt);
v[x]:=ord(ch)-ord('a')+;
pushup(x);
end;
'I':begin
read(z);read(ch);readln(ch);
x:=find(rt,z+);y:=find(rt,z+);
splay(x,rt);splay(y,c[x,]);
inc(tot);c[y,]:=tot;fa[tot]:=y;s[tot]:=;
v[tot]:=ord(ch)-ord('a')+;w[tot]:=v[tot];
pushup(y);pushup(x);
end;
'Q':begin
readln(x,y);
writeln(query(x,y));
end;
end;
end;
end;
begin
assign(input,'input.txt');assign(output,'output.txt');
reset(input);rewrite(output);
init;
main;
close(input);close(output);
end.

2.在网上找了一份,模版和我的差不多  AC

 program hy_;
const maxn=;
var h:array[..] of int64;
d:array[..] of int64;
a,sum:array[..] of int64;
fa:array[..] of longint;
ll,rr:array[..] of longint;
c:array[..,..] of longint;
size,k,kk,root,n,m,all:longint;
hh,ch:array[..] of char;
//============================================================================
procedure update(x:longint);
var p,q:longint;
begin
sum[x]:=sum[c[x,]]+sum[c[x,]]+;
p:=c[x,]; q:=c[x,];
h[x]:=(h[p]+a[x]*d[sum[p]+]+h[q]*d[sum[p]+]) mod maxn; //更新hash值。
end;
//============================================================================
procedure build(l,r:longint); //一开始用递归建树,防止树的深度太大。
var mid,tmp:longint;
begin
mid:=(l+r) shr ;
if mid>l then
begin
build(l,mid-);
tmp:=(l+mid-) shr ;
c[mid,]:=tmp; fa[tmp]:=mid;
end;
if mid<r then
begin
build(mid+,r);
tmp:=(mid++r) shr ;
c[mid,]:=tmp; fa[tmp]:=mid;
end; update(mid);
end;
//============================================================================
procedure init;
var i,len:longint;
st:ansistring;
chh:char;
begin
readln(st); len:=length(st);
for i:= to len+ do //在头尾预留两个单元,splay时就总能找到l-和r+。
begin
a[i]:=ord(st[i-])-ord('a');
h[i]:=a[i];
end; d[]:=;
for i:= to do
d[i]:=(d[i-]*) mod maxn; //预处理k的n次方(见hash函数)。
build(,len+); root:=(len+) shr ;
readln(m); size:=len+;
for i:= to m do
begin
read(ch[i]);
if ch[i]='Q' then
begin
inc(all); readln(ll[i],rr[i]);
end else readln(ll[i],chh,hh[i]);
end;
end;
//============================================================================
function find(x:longint):longint;
begin
if sum[c[x,]]+=k then exit(x);
if sum[c[x,]]<k- then
begin
dec(k,sum[c[x,]]+);
find:=find(c[x,]);
end else find:=find(c[x,]);
end;
//============================================================================
procedure rotate(var root:longint; x:longint);
var y,z,p,q:longint;
begin
y:=fa[x]; z:=fa[y];
if c[y,]=x then p:= else p:=;
q:=p xor ;
if y=root then root:=x else
if c[z,]=y then c[z,]:=x else c[z,]:=x;
fa[x]:=z; fa[y]:=x; fa[c[x,q]]:=y;
c[y,p]:=c[x,q]; c[x,q]:=y;
update(y); update(x);
end;
//============================================================================
procedure splay(var root:longint; x:longint);
var y,z:longint;
begin
while x<>root do
begin
y:=fa[x]; z:=fa[y];
if y<>root then
if (c[y,]=x) xor (c[z,]=y) then
rotate(root,x) else rotate(root,y);
rotate(root,x);
end;
end;
//============================================================================
procedure insert(x:longint);
begin
if x= then
begin
inc(size); h[size]:=kk; sum[size]:=;
a[size]:=h[size]; exit;
end;
if sum[c[x,]]>=k then
begin
insert(c[x,]);
if c[x,]= then begin c[x,]:=size; fa[size]:=x; end;
end else
begin
k:=k-sum[c[x,]]-; insert(c[x,]);
if c[x,]= then begin c[x,]:=size; fa[size]:=x; end;
end; update(x);
end;
//============================================================================
procedure ask(x:longint);
var xx,yy,l,r,ans,l1,l2,left1,left2:longint;
hash1,hash2,s,t,mid,tt:longint;
begin
if rr[x]<ll[x] then
begin
tt:=rr[x]; rr[x]:=ll[x]; ll[x]:=tt;
end;
if ll[x]=rr[x] then
begin writeln(size--ll[x]); exit; end;
k:=ll[x]; l:=find(root); splay(root,l);
k:=rr[x]; r:=find(root);
k:=ll[x]+; xx:=find(root); k:=rr[x]+; yy:=find(root);
if a[xx]<>a[yy] then
begin writeln(''); exit; end;
s:=; t:=size-rr[x]-; ans:=;
k:=ll[x]+t+; l1:=find(root);
k:=rr[x]+t+; l2:=find(root);
splay(c[root,],l1); hash1:=h[c[l1,]];
splay(c[root,],r); splay(c[r,],l2); hash2:=h[c[l2,]];
if hash1=hash2 then begin writeln(t); exit; end; //这里特判了最长长度的串。。有的数据太猥琐。。。
dec(t);
repeat
mid:=(s+t) shr ;
k:=ll[x]+mid+; l1:=find(root);
k:=rr[x]+mid+; l2:=find(root);
splay(c[root,],l1); hash1:=h[c[l1,]];
splay(c[root,],r); splay(c[r,],l2); hash2:=h[c[l2,]];
if hash1=hash2 then
begin s:=mid+; ans:=mid; end else t:=mid-;
until s>t; writeln(ans);
end;
//============================================================================
procedure rep(x:longint);
var z,p,q:longint;
begin
k:=ll[x]+; z:=find(root); splay(root,z);
a[z]:=ord(hh[x])-ord('a'); p:=c[root,]; q:=c[root,];
h[z]:=(h[p]+a[z]*d[sum[p]+]+h[q]*d[sum[p]+]);
end;
//============================================================================
procedure ins(x:longint);
begin
k:=ll[x]+; kk:=ord(hh[x])-ord('a'); insert(root);
splay(root,size);
end;
//============================================================================
procedure work;
var i:longint;
begin
for i:= to m do
begin
if ch[i]='Q' then
begin
ask(i); dec(all);
if all= then halt;
end else if ch[i]='R' then rep(i) else ins(i);
end;
end;
//============================================================================
begin
assign(input,'input.txt');assign(output,'output2.txt');
reset(input);rewrite(output);
init;
work;
close(input);close(output);
end.

JSOI2008 火星人prefix的更多相关文章

  1. 1014: [JSOI2008]火星人prefix

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Description 火星人最近研究了一种操作:求一个字串两个后缀 ...

  2. [BZOJ1014][JSOI2008]火星人prefix

    [BZOJ1014][JSOI2008]火星人prefix 试题描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字 ...

  3. BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6243  Solved: 2007[Submit] ...

  4. 【bzoj1014】[JSOI2008]火星人prefix

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6031  Solved: 1917[Submit] ...

  5. BZOJ 1014: [JSOI2008]火星人prefix Splay+二分

    1014: [JSOI2008]火星人prefix 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人 ...

  6. bzoj 1014: [JSOI2008]火星人prefix hash && splay

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3154  Solved: 948[Submit][ ...

  7. 求帮看!!!!BZOJ 1014 [JSOI2008]火星人prefix

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4164  Solved: 1277[Submit] ...

  8. BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )

    用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...

  9. 2018.06.28 BZOJ1014 [JSOI2008]火星人prefix(非旋treap+hash)

    [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Submit: 8951 Solved: 2860 Description 火星 ...

随机推荐

  1. JS调用PHP 和 PHP调用JS的方法举例

    http://my.oschina.net/jiangchike/blog/220988 1.JS方式调用PHP文件并取得PHP中的值举一个简单的例子来说明:如在页面test_json1中用下面这句调 ...

  2. mysql笔记之集群

    1.主从配置 #主从都要加入以下配置如下 [mysqld] log-bin=mysql-bin #主从要不一样 server-id=222 #在主上建立一个用户给从的用 GRANT REPLICATI ...

  3. prototype原型链继承

    依旧是恶补js基础,上代码: 1.定义父类及父类方法 function Animal(){ this.name = "动物"; } Animal.prototype.eat = f ...

  4. sql中truncate 、delete与drop区别

    SQL truncate .delete与drop区别   相同点: 1.truncate和不带where子句的delete.以及drop都会删除表内的数据. 2.drop.truncate都是DDL ...

  5. UVA 11078 Open Credit System(扫描 维护最大值)

    Open Credit System In an open credit system, the students can choose any course they like, but there ...

  6. 简单的一个makefile

    cpp_obj = $(patsubst %.cpp, %.o, $(wildcard *.cpp)) bin : $(cpp_obj) g++ -o bin $(cpp_obj) .PHONY : ...

  7. jQuery选择器(适合初学者哟....)

    选择器是jQuery最基础的东西,本文中列举的选择器基本上囊括了所有的jQuery选择器,也许各位通过这篇文章能够加深对jQuery选择器的理解,它们本身用法就非常简单,我更希望的是它能够提升个人编写 ...

  8. 构建 shiro struts2 spring3 mybatis 的maven项目

    书接上回 构建 struts2 spring3 mybatis 的maven项目 构建 pom.xml 继续在原有框架下 融合shiro ,具体shiro是啥 这里就不解释了,恩 反正功能挺强大的 本 ...

  9. js实现幻灯片播放图片示例代码

    幻灯片播放图片的效果想必大家都有见到过吧,下面有个不错的示例,感兴趣的朋友可以参考下 复制代码代码如下: <select id="img_date" style=" ...

  10. C语言2048

    这段时间google上有个小游戏挺火的,我也很喜欢,业余时间做个C语言版的. 老规矩先上干货: http://files.cnblogs.com/GhostZCH/2048.rar (.c & ...