可持久化数组

Posted Halifuda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可持久化数组相关的知识,希望对你有一定的参考价值。

技术分享图片
#include<cstdio>
#define MXN 1000000+1
#define mid(a,b) ((a+b)>>1)
int read(){
    int x=0,w=1;
    char c=getchar();
    while(c<0||c>9){
        if(c==-) w=-1;
        c=getchar();
    }
    while(c>=0&&c<=9){
        x=(x<<3)+(x<<1)+(c-0);
        c=getchar();
    }
    return x*w;
}
int arr[MXN];
unsigned int num,q;
struct Node{
    int val;
    Node *left,*right;
}node[23*MXN],*root[MXN];
int node_num=-1,rtop=-1;
void update(Node *now){
    Node *nl,*nr;
    nl=now->left;
    nr=now->right;
    if(nl!=NULL) now->val=nl->val;
    if(nr!=NULL) now->val=nr->val;
    return;
}
Node* newnode(){
    Node *n;
    n=&node[++node_num];
    n->val=0;
    n->left=NULL;
    n->right=NULL;
    return n;
}
Node* newnode(Node *now){
    Node *n;
    n=&node[++node_num];
    n->val=now->val;
    n->left=now->left;
    n->right=now->right;
    return n;
}
void build(Node *now,int bl,int br){
    if(bl==1&&br==num) root[++rtop]=now;
    if(bl==br){
        now->val=arr[bl];
        return;
    }
    Node *nl,*nr;
    nl=newnode();
    nr=newnode();
    now->left=nl;
    now->right=nr;
    build(nl,bl,mid(bl,br));
    build(nr,mid(bl,br)+1,br);
    update(now);
    return;
}
Node* change(Node *now,int k,int al,int ar,int l,int r){
    if(l>ar||r<al) return NULL;
    Node *n;
    if(l<=al&&ar<=r){
        n=newnode(now);
    }
    if(al<=l&&r<=ar){
        n->val=k;
    }
    else{
        Node *ls,*rs;
        ls=n->left;
        rs=n->right;
        if(n->left!=NULL&&l<=al&&ar<=mid(l,r)){
            n->left=newnode(ls);
            n->left=change(n->left,k,al,ar,l,mid(l,r));
        }
        if(n->right!=NULL&&mid(l,r)+1<=al&&ar<=r){
            n->right=newnode(rs);
            n->right=change(n->right,k,al,ar,mid(l,r)+1,r);
        }
        update(n);
    }
    if(l==1&&r==num) root[++rtop]=n;
    return n;
}
Node* ques(Node *now,int ql,int qr,int l,int r){
    if(r<ql||qr<l) return now;
    Node *n;
    if(l<=ql&&qr<=r){
        n=newnode(now);
    }
    if(ql<=l&&r<=qr) return n;
    Node *ls,*rs;
    ls=n->left;
    rs=n->right;
    if(n->left!=NULL&&l<=ql&&qr<=mid(l,r)){
        n->left=newnode(ls);
        n->left=ques(n->left,ql,qr,l,mid(l,r));
    }
    if(n->right!=NULL&&mid(l,r)+1<=ql&&qr<=r){
        n->right=newnode(rs);
        n->right=ques(n->right,ql,qr,mid(l,r)+1,r);
    }
    update(n);
    if(l==1&&r==num) root[++rtop]=n;
    return n;
}
int find(Node *now,int ql,int qr,int l,int r){
    if(r<ql||qr<l) return 0;
    if(ql<=l&&r<=qr) return now->val;
    if(now->left!=NULL&&l<=ql&&qr<=mid(l,r)){
        return find(now->left,ql,qr,l,mid(l,r));
    }
    if(now->right!=NULL&&mid(l,r)+1<=ql&&qr<=r){
        return find(now->right,ql,qr,mid(l,r)+1,r);
    }
}
int main(){
    num=read();
    q=read();
    for(int i=1;i<=num;i++) arr[i]=read();
    build(newnode(),1,num);
    for(int i=0;i<q;i++){
        int edt,p,a,b;
        edt=read();
        p=read();
        if(p==1){
            a=read();
            b=read();
            change(root[edt],b,a,a,1,num);
        }
        if(p==2){
            a=read();
            ques(root[edt],a,a,1,num);
            printf("%d\n",find(root[rtop],a,a,1,num));
        }
    }
    return 0;
}
可持久化数组

我交的题是洛谷P3919。

我要谴责一下这道题。

我写的是指针。

MLE了。

mmp。

就不能照顾一下指针党吗。

调了一天。

我上面的代码是提交效果最好的一次。

23,1000000+1这两个参数是我二分出来的,只有这组可以MLE两个点,其他参数会RE。

虽然爆粗很对不起,但是我现在心态爆炸了,所以大家容忍一下。

以上是关于可持久化数组的主要内容,如果未能解决你的问题,请参考以下文章

持久片段和查看器

ZOJ2112 Dynamic Rank(可持久化线段树套树状数组)

ZOJ2112 Dynamic Rank(可持久化线段树套树状数组)

精心收集的 48 个 JavaScript 代码片段,仅需 30 秒就可理解!(转载)

P3919 模板可持久化数组(可持久化线段树/平衡树)

P3919 模板可持久化数组(可持久化线段树/平衡树)