[BZOJ1014] [JSOI2008]火星人prefix

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=1014

题目大意

给定字符串,要求支持
1.求lcp
2.修改某一位字符
3.插入字符

题解

因为要插入,所以用Splay维护子树表示的字符串的HASH值,然后就是细节啦
求lcp二分即可
Splay写了1个半点,QAQAQ,再颓废就真废了XD

const
    maxn=100010;
    seed=131;
    mmod=maxlongint;
var
    w:array[-1..2*maxn,1..5]of longint; {1.左儿子2.右儿子3.父4.子树节点和5.点ord值}
    hash,pow:array[-1..2*maxn]of longint;
    i,j,k:longint;
    n,m,a,b,len,root,leng:longint;
    cha,ch:char;
procedure print(a:longint);
begin
    if w[a,1]<>-1 then print(w[a,1]);
    write(chr(w[a,5]));
    if w[a,2]<>-1 then print(w[a,2]);
    if a=root then writeln;
end;

procedure change(a:longint);
var ls,rs:longint;
begin
    ls:=w[a,1]; rs:=w[a,2];
    hash[a]:=(int64(hash[rs])+int64(hash[ls])*pow[w[rs,4]+1]+int64(w[a,5])*pow[w[rs,4]])mod mmod;
end;

function max(a,b:longint):longint;
begin if a>b then exit(a) else exit(b); end;

procedure rotate(a,kind:longint);
var b,unkind:longint;
begin
    unkind:=kind xor 3; b:=w[a,3];
    w[a,4]:=w[b,4]; w[b,4]:=1+w[w[a,unkind],4]+w[w[b,unkind],4];
    w[w[a,unkind],3]:=b; w[b,kind]:=w[a,unkind];
    w[a,3]:=w[b,3]; w[b,3]:=a; w[a,unkind]:=b;
    if w[w[a,3],1]=b
    then w[w[a,3],1]:=a
    else w[w[a,3],2]:=a;
    change(a); change(b);
end;

procedure splay(a,goal:longint);
var kind,unkind,b:longint;
begin
    while w[a,3]<>goal do
        begin
            b:=w[a,3]; if w[b,1]=a then kind:=1 else kind:=2; unkind:=kind xor 3;
            if w[b,3]=goal then rotate(a,kind)
            else
                if w[w[b,3],kind]=b
                then begin rotate(b,kind); rotate(a,kind); end
                else begin rotate(a,kind); rotate(a,unkind); end;
        end;
    if goal=-1 then root:=a;
end;

function find(pos:longint):longint;
var tt:longint;
begin
    tt:=root;
    while w[w[tt,1],4]<>pos-1 do
        if w[w[tt,1],4]>=pos
        then tt:=w[tt,1]
        else begin dec(pos,w[w[tt,1],4]+1); tt:=w[tt,2]; end;
    exit(tt);
end;

function check(a,b,c:longint):longint;
var t1,t2:longint;
begin
    if c=0 then exit(1);
    splay(find(a-1),-1); splay(find(a+c),root); t1:=hash[w[w[root,2],1]];
    splay(find(b-1),-1); splay(find(b+c),root); t2:=hash[w[w[root,2],1]];
    if t1=t2 then exit(1) else exit(0);
end;

function query(a,b:longint):longint;
var l,r,mid,ans:longint;
begin
    l:=0; r:=leng+1-max(a,b)+1; ans:=0;
    while l<=r do
        begin
            mid:=(l+r)>>1;
            if check(a,b,mid)=1
            then begin ans:=mid; l:=mid+1; end
            else r:=mid-1;
        end;
    exit(ans);
end;

procedure insert(pos:longint; ch:char);
var tt,fa:longint;
begin
    tt:=find(pos);
    splay(tt,-1);
    hash[root]:=(int64(hash[w[root,2]])+int64(ord(ch))*pow[w[w[root,2],4]]+int64(w[root,5])*pow[w[w[root,2],4]+1]+int64(hash[w[root,1]])*pow[w[w[root,2],4]+2])mod mmod;
    inc(w[root,4]);
    tt:=w[w[root,2],1]; fa:=w[root,2];
    while tt<>-1 do
        begin
            hash[tt]:=(int64(hash[tt])+int64(ord(ch))*pow[w[tt,4]])mod mmod;
            inc(w[tt,4]);
            fa:=tt; tt:=w[tt,1];
        end;
    inc(len); w[len,1]:=-1; w[len,2]:=-1; w[len,3]:=fa; w[len,4]:=1; w[len,5]:=ord(ch); w[fa,1]:=len; hash[len]:=ord(ch);
    splay(len,-1);
end;

procedure update(pos:longint; ch:char);
var tt:longint;
begin
    tt:=find(pos);
    splay(tt,-1);
    w[root,5]:=ord(ch);
    change(root);
end;

begin
    pow[0]:=1;
    for i:=1 to maxn do
        pow[i]:=(int64(pow[i-1])*seed)mod mmod;
    len:=2; root:=1;
    w[1,1]:=-1; w[1,2]:=2; w[1,3]:=-1; w[1,4]:=2; w[1,5]:=ord('#'); hash[1]:=(ord('#')*seed+ord('#'))mod mmod;
    w[2,1]:=-1; w[2,2]:=-1; w[2,3]:=1; w[2,4]:=1; w[2,5]:=ord('#'); hash[2]:=ord('#')mod mmod;
    i:=0; leng:=0;
    while not eoln do
        begin
            inc(i); inc(leng);
            read(cha);
            insert(i,cha);
        end;
    readln;
    readln(m);
    for i:=1 to m do
        begin
            read(cha);
            case cha of
            'Q':begin readln(a,b); writeln(query(a+1,b+1)); end;
            'R':begin readln(a,ch,ch); update(a+1,ch); end;
            'I':begin readln(a,ch,ch); insert(a+1,ch); inc(leng); end;
            end;
        end;
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述 有一个 $n$ 个点的棋盘,每个点上有一个数字 $a_i$,你需要从 $(1,1)$ 走到 $(n,n)$,每次只能往右或往下走,每个格子只能经过一次,路径上的数字和为 $S$。定义一个点 $(x,y)$ 的权值为 $a_x+a_y$,求所有满足条件的路径中,所有点的权值和的最小值。 输入格式 第一行一个整数 $n$。 接下来 $n$ 行,每行 $n$ 个整数,表示棋盘上每个点的数字。 输出格式 输出一个整数,表示所有满足条件的路径中,所有点的权值和的最小值。 数据范围 $1\leq n\leq 300$ 输入样例 3 1 2 3 4 5 6 7 8 9 输出样例 25 算法1 (树形dp) $O(n^3)$ 我们可以先将所有点的权值求出来,然后将其看作是一个有权值的图,问题就转化为了在这个图中求从 $(1,1)$ 到 $(n,n)$ 的所有路径中,所有点的权值和的最小值。 我们可以使用树形dp来解决这个问题,具体来说,我们可以将这个图看作是一棵树,每个点的父节点是它的前驱或者后继,然后我们从根节点开始,依次向下遍历,对于每个节点,我们可以考虑它的两个儿子,如果它的两个儿子都被遍历过了,那么我们就可以计算出从它的左儿子到它的右儿子的路径中,所有点的权值和的最小值,然后再将这个值加上当前节点的权值,就可以得到从根节点到当前节点的路径中,所有点的权值和的最小值。 时间复杂度 树形dp的时间复杂度是 $O(n^3)$。 C++ 代码 算法2 (动态规划) $O(n^3)$ 我们可以使用动态规划来解决这个问题,具体来说,我们可以定义 $f(i,j,s)$ 表示从 $(1,1)$ 到 $(i,j)$ 的所有路径中,所有点的权值和为 $s$ 的最小值,那么我们就可以得到如下的状态转移方程: $$ f(i,j,s)=\min\{f(i-1,j,s-a_{i,j}),f(i,j-1,s-a_{i,j})\} $$ 其中 $a_{i,j}$ 表示点 $(i,j)$ 的权值。 时间复杂度 动态规划的时间复杂度是 $O(n^3)$。 C++ 代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值