POJ2887

这题我一开始复制模板,用的是指针式splay,微调了一下就交了,发现poj坏了(submmited failed)
今天一看,发现WA了,原来是insert到右子树时忘记把期望插入的位置减去 size+1 ,改完后T了
百度题解,发现别人都用块状链表,这不科学啊, logn 怎么可能比 n 慢这么多(本机测试得耗时至少多一倍),看来splay常数太大
改成手写内存池,更慢了。
改成数组,终于 641ms 2602B AC了。
然后看了看别人代码,有位小哥 266ms , 993B AC了,顿觉人生失去希望,为什么一开始要作死写splay

//#pragma GCC optimize("O2")
#include <cstdio>
#include <cstring>
#include <ctime>
const int N=1100000;
int n,x;
char c[N],a[5],b[5];
struct list{
    int xb,rt;
    struct node{
        int l,r,fa,size;
        char v;
        node(char _v=0):v(_v){size=1,l=r=fa=0;}
    }a[N];
    void maintain(int i){
        a[i].size=a[a[i].l].size+a[a[i].r].size+1;
    }
    void rorate(int x){
        int y=a[x].fa,z=a[y].fa;        
        if(z){
            if(a[z].l==y)a[z].l=x;
                else a[z].r=x;
        }
        a[x].fa=z;
        a[y].fa=x;
        if(a[y].l==x){
            a[a[x].r].fa=y;
            a[y].l=a[x].r;
            a[x].r=y;
        }else{
            a[a[x].l].fa=y;
            a[y].r=a[x].l;
            a[x].l=y;
        }
        maintain(y);
        maintain(x);
    }
    void splay(int x){
        while(a[x].fa){
            int y=a[x].fa,z=a[y].fa;
            if(z){                
                if((a[y].l==x)^(a[z].l==y))rorate(x);
                    else rorate(y);
            }
            rorate(x);
        }
        rt=x;
    }
    char& operator[](int i){//1<=i<=rt->size
        int x=rt;
        for(;;){
            int y=a[a[x].l].size+1;
            if(y>i)x=a[x].l;
                else if(y<i){
                    i-=y;
                    x=a[x].r;
                }else return a[x].v;
        }
    }
    int ins(int&aa,int b,char c){
        if(!aa)return a[aa=++xb]=node(c),xb;
        int x=a[a[aa].l].size,u;
        if(b<=x){
            u=ins(a[aa].l,b,c);
            maintain(aa);
        }else{
            u=ins(a[aa].r,b-x-1,c);
            maintain(aa);
        }
        if(!a[u].fa)a[u].fa=aa;
        return u;
    }
    inline void push_back(char c){
        int x=rt;
        while(a[x].r)++a[x].size,x=a[x].r;
        a[a[x].r=++xb]=node(c);
        a[a[x].r].fa=x;
        splay(a[x].r);
    }
    void insert(int i,char c){
        if(i>a[rt].size)push_back(c);
            else splay(ins(rt,i,c));
    }
    void build(int fa,int&x,char*first,char*last){
        a[x=++xb].fa=fa;
        char *m=first+((last-first)>>1);
        a[x].v=*m;
        if(m!=first)build(x,a[x].l,first,m-1);
        if(m!=last)build(x,a[x].r,m+1,last);
        maintain(x);
    }
    void operator=(char*c){
        build(0,rt,c,c+strlen(c)-1);
    }
    void midout(int i){
        if(i){
            midout(a[i].l);
            putchar(a[i].v);
            midout(a[i].r);
        }
    }
}l;
int main(){
    //freopen("a.txt","r",stdin);
    //freopen("wa.txt","w",stdout);
    scanf("%s%d",c+1,&n);
    l.a[0].size=0;
    l=c+1;
    while(n--){
        scanf("%s",a);
        if(*a=='I'){
            scanf("%s%d",b,&x);
            l.insert(x-1,*b);
        }else{
            scanf("%d",&x);
            putchar(l[x]);
            putchar('\n');
        }
    }
    return 0;
}

upd:后来我也用vector,写了遍块链,块大小设为3500时耗时391ms,代码长度621B

#include<stdio.h>
#include<vector>
using std::vector;
const int sz=3500,bs=550;
int n,i,xb,x,l;
char a[5],b[5],c[sz*bs];
vector<char> v[bs];
int main(){
    scanf("%s",c+1);
    xb=1;
    for(i=1;c[i];++i){
        v[xb].push_back(c[i]);
        if(v[xb].size()==sz)++xb;
    }
    l=i-1;
    scanf("%d",&n);
    while(n--){
        scanf("%s",a);
        if(*a=='Q'){
            scanf("%d",&x);
            for(i=1;x>(int)v[i].size();++i)x-=v[i].size();
            putchar(v[i][x-1]),putchar('\n');
        }else{
            scanf("%s%d",b,&x);
            if(x<=l){
                for(i=1;x>(int)v[i].size();++i)x-=v[i].size();
                v[i].insert(v[i].begin()+x-1,*b);
            }else v[xb].push_back(*b);
            ++l;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值