洛谷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宠物收养场·改的主要内容,如果未能解决你的问题,请参考以下文章