洛谷P2286宠物收养场·改

Posted Halifuda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P2286宠物收养场·改相关的知识,希望对你有一定的参考价值。

技术分享图片
#include<cstdio>
#define abs(a,b) (a>b?a-b:b-a)
#define MOD 1000000
#define MXN 80000+5
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 ans;
struct Node{
    int val;
    bool type;
    Node *fa,*left,*right;
}node[MXN],*root,*recycle[MXN];
int n,p,x,node_num=-1,top=-1;
bool tree_type;
void rotate(Node *now){
    if(now->fa==NULL) return;
    Node *f,*gf,*l,*r;
    f=now->fa;
    gf=f->fa;
    l=now->left;
    r=now->right;
    now->fa=gf;
    if(gf!=NULL){
        if(gf->left==f) gf->left=now;
        if(gf->right==f) gf->right=now;
    }
    if(f->left==now){
        now->right=f;
        f->left=r;
        if(r!=NULL) r->fa=f;
    }
    if(f->right==now){
        now->left=f;
        f->right=l;
        if(l!=NULL) l->fa=f;
    }
    f->fa=now;
    if(now->fa==NULL) root=now;
    return;
}
void splay(Node *now,Node *des){
    if(now==des) return;
    Node *f,*gf;
    while(now->fa!=des){
        f=now->fa;
        gf=f->fa;
        if(gf==des) rotate(now);
        else if(gf->left==f&&f->right==now){
            rotate(now);
            rotate(now);
        }
        else if(gf->right==f&&f->left==now){
            rotate(now);
            rotate(now);
        }
        else if(gf->left==f&&f->left==now){
            rotate(f);
            rotate(now);
        }
        else if(gf->right==f&&f->right==now){
            rotate(f);
            rotate(now);
        }
    }
    if(now->fa==NULL) root=now;
    return;
}
Node* node_new(int vl,bool typ){
    Node *n;
    if(top!=-1){
        n=recycle[top];
        top--;
    }
    else{
        node_num++;
        n=&node[node_num];
    }
    n->val=vl;
    n->type=typ;
    n->left=NULL;
    n->right=NULL;
    n->fa=NULL;
    return n;
}
void node_insert(Node *now,Node *v){
    if(root==NULL){
        root=v;
        tree_type=v->type;
        return;
    }
    if(now==NULL){
        *now=*v;
        return;
    }
    if(v->val<=now->val){
        if(now->left==NULL){
            now->left=v;
            v->fa=now;
        }
        else node_insert(now->left,v);
    }
    if(v->val>now->val){
        if(now->right==NULL){
            now->right=v;
            v->fa=now;
        }
        else node_insert(now->right,v);
    }
    splay(v,NULL);
    return;
}
Node* root_prev(){
    Node *t;
    if(root->left!=NULL){
        t=root->left;
        while(t->right!=NULL) t=t->right;
        return t;
    }
    else return NULL;
}
Node* root_subs(){
    Node *t;
    if(root->right!=NULL){
        t=root->right;
        while(t->left!=NULL) t=t->left;
        return t;
    }
    else return NULL;
}
void node_delete(Node *now){
    recycle[++top]=now;
    splay(now,NULL);
    root=now;
    if(now->left==NULL&&now->right==NULL){
        root=NULL;
        return;
    }
    if(now->left==NULL){
        root=now->right;
        root->fa=NULL;
        return;
    }
    if(now->right==NULL){
        root=now->left;
        root->fa=NULL;
        return;
    }
    Node *l,*r;
    l=now->left;
    r=now->right;
    l->fa=NULL;
    Node *t=now->left;
    while(t->right!=NULL) t=t->right;
    splay(t,NULL);
    t->right=r;
    r->fa=t;
    root=t;
    return;
}
void ques(Node *now){
    node_insert(root,now);
    if(now->type==tree_type) return;
    else{
        splay(now,NULL);
        Node *p,*s,*a;
        p=root_prev();
        s=root_subs();
        a=p;
        int t1,t2;
        if(p!=NULL) t1=abs(p->val,now->val);
        else t1=1<<30;
        if(s!=NULL) t2=abs(s->val,now->val);
        else t2=1<<30;
        if(t2<t1){
            a=s;
            ans+=t2;
        }
        else ans+=t1;
        ans%=MOD;
        node_delete(now);
        node_delete(a);
    }
    return;
}
int main(){
    root=NULL;
    n=read();
    for(int i=0;i<n;i++){
        p=read();
        x=read();
        ques(node_new(x,(bool)p));
    }
    printf("%d",ans);
    return 0;
}
优化代码

这次修改了一下上次写的代码。

由于本人建树的方法属于静态分配内存(动态分配总会出现玄学错误...),因此内存空间要开很大很大才不会RE,删除节点后,上一次的代码没有垃圾回收,导致空间复杂度稍大(上一次大约O(5n)才过去)。

这次开了一个栈,命名为recycle回收站,每次删除节点后,地址丢到回收站,创造新节点时,先检查回收站里有没有空闲地址,有就用,没有才在静态内存空间里找一个地址分配。这样空间复杂度变为了O(2n),降低了很多(实际上从4.31MB降到了2.21MB)。

不过感觉回头还是学一下动态分配吧...

以上是关于洛谷P2286宠物收养场·改的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P2286宠物收养场

宠物收养场 Treap

[HNOI 2004]宠物收养场

[HNOI2004]宠物收养场——treap

1208. [HNOI2004]宠物收养场平衡树-splay

HNOI2004 宠物收养场 [Treap]