[JSOI2008]火星人

Posted $mathcal{color{skyblue}{\_Orch

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JSOI2008]火星人相关的知识,希望对你有一定的参考价值。

这个题目我成功爆零,\(\color{blue}{TTTTTLE}\)了全部的点……我可真棒啊……

\(\color{red}{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\)函数的值。

\(\color{red}{Input}\)

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

\(\color{red}{Output}\)

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

\(\color{red}{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

\(\color{red}{Sample \ \ Output}\)

5
1
0
2
1

\(\color{red}{HINT}\)

1、所有字符串自始至终都只有小写字母构成。

2、\(M<=150,000\)

3、字符串长度L自始至终都满足L<=100,000

4、询问操作的个数不超过10,000个。

对于第1,2个数据,字符串长度自始至终都不超过1,000

对于第3,4,5个数据,没有插入操作。

\(\color{purple}{Half-solution}\)

咳,对比着记录吧,我暂时只会\(TLE\)版本的暴力,先贴上来记录我光辉的历史

插入就是插入,修改就是修改,但是因为事实上我当时\(Splay\)只学了一半,所以现在对区间\(Splay\)无所适从\(OTZ\)……

嗯,那么查询的话,就是不断查询自己的父节点,或者右子节点,但是由于你\(Splay\)的话会使得序列无序,所以并不可做。

那么事实上你看,这其实是一个会\(WA\)但是先\(TLE\)了的算法。

哈哈哈我还调试了半天。

真有趣。

#include<iostream>
#include<cstdio>
#define MAXN 250001
#define il inline 
using namespace std;
struct chars{
    unsigned int son[2],f,sub;
    char v;
}s[MAXN];
char t,base[MAXN],cc;
unsigned int k,res;
unsigned int xx,yy,m,a,b,i,qwq,root,wz,now,fnow,ffnow;
il bool w(unsigned int x){
    return x==s[s[x].f].son[1];
}
il void push_up(unsigned int x){
    if(x){
        s[x].sub=1;
        if(s[x].son[1])s[x].sub+=s[s[x].son[1]].sub;
        if(s[x].son[0])s[x].sub+=s[s[x].son[0]].sub;
    }
}
il void rotate(unsigned int x){
    fnow=s[x].f,ffnow=s[fnow].f;
    bool ww=w(x);
    s[fnow].son[ww]=s[x].son[ww^1];
    s[s[fnow].son[ww]].f=fnow;
    s[fnow].f=x;
    s[x].f=ffnow;
    s[x].son[ww^1]=fnow;
    if(ffnow){
        s[ffnow].son[s[ffnow].son[1]==fnow]=x;
    }
    push_up(fnow);
    push_up(x);
}
void splay(unsigned int x,unsigned int goal){
    for(qwq;(qwq=s[x].f)!=goal;rotate(x)){
        if(s[qwq].f!=goal){
            rotate(w(x)==w(qwq)?qwq:x);
        }
    }
    if(goal==0){
        root=x;
    }
}

void insert(unsigned int pos,char c){
    if(!wz){
        wz++;
        root=wz;
        s[wz].f=s[wz].son[1]=s[wz].son[0]=0;
        s[wz].sub++;
        s[wz].v=c;
        return ;
    }
    if(!pos){
        wz++;
        s[wz].son[1]=root,s[wz].v=c;
        s[root].f=wz;
        root=wz;
        push_up(wz);
        return ;
    }
    now=root;
    while(1){
        if(s[now].son[0]&&pos<=s[s[now].son[0]].sub)
        now=s[now].son[0];
        else {
            unsigned int temp=(s[now].son[0]?s[s[now].son[0]].sub:0)+1;
            if(pos<=temp)break;
            pos-=temp;
            now=s[now].son[1];
        }
    }
    wz++;
    s[wz].son[1]=s[now].son[1];
    s[s[now].son[1]].f=wz;
    s[now].son[1]=wz;
    s[wz].f=now;
    s[wz].v=c;
    push_up(wz);
    push_up(now);
    //splay(wz,0);
}

il void update(unsigned int pos,char c){
    now=root;
    while(1){
        if(s[now].son[0]&&pos<=s[s[now].son[0]].sub)
        now=s[now].son[0];
        else {
            unsigned int temp=(s[now].son[0]?s[s[now].son[0]].sub:0)+1;
            if(pos<=temp)break;
            pos-=temp;
            now=s[now].son[1];
        }
    }
    s[now].v=c;
//    splay(now,0);
}
il unsigned int find(unsigned int sx,unsigned int sy){
    xx=root,res=0,yy=root;
    while(1){
        if(s[xx].son[0]&&sx<=s[s[xx].son[0]].sub)
        xx=s[xx].son[0];
        else {
            unsigned int temp=(s[xx].son[0]?s[s[xx].son[0]].sub:0)+1;
            if(sx<=temp)break;
            sx-=temp;
            xx=s[xx].son[1];
        }
    }
    while(1){
        if(s[yy].son[0]&&sy<=s[s[yy].son[0]].sub)
        yy=s[yy].son[0];
        else {
            unsigned int temp=(s[yy].son[0]?s[s[yy].son[0]].sub:0)+1;
            if(sy<=temp)break;
            sy-=temp;
            yy=s[yy].son[1];
        }
    }
    while(1){
        if(s[yy].v==s[xx].v)res++;
        yy=s[yy].son[1];
        xx=s[xx].son[1];
        if(!yy||!xx||s[yy].v!=s[xx].v){
            return res;
        }
    }
}
il unsigned int qread(){
    k=0,cc=getchar();
    while(!isdigit(cc)){
        cc=getchar();
    }
    while(isdigit(cc)){
        k=(k<<1)+(k<<3)+cc-48;
        cc=getchar();
    }
    return k;
}
int main(){
    scanf("%s",base);
    m=qread();
    for(i=0;base[i];i++){
        insert(i,base[i]);
    }
    for(i=1;i<=m;i++){
        scanf("%c",&t);
        if(t==‘I‘){
            a=qread();
            scanf("%c",&t);
            insert(a,t);
            continue;
        }
        else if(t==‘R‘){
            a=qread();
            scanf("%c",&t);
            update(a,t);
            continue;           
        }
        a=qread();
        b=qread();
        printf("%d\n",find(a,b));
    }
    return 0;
}

以上已经被挂在了历史的耻辱柱上



























以上是关于[JSOI2008]火星人的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1014[JSOI2008]火星人prefix

bzoj1014: [JSOI2008]火星人prefix

[JSOI2008]火星人prefix

JSOI2008火星人

[JSOI2008]火星人

[BZOJ1014][JSOI2008]火星人prefix