Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
精诚所至金石为开,发帖向路过的大牛们求救!In Reply To:splay竟然超时了。这题有什么特别需要注意的吗? Posted by:AllwaysLoser at 2009-04-25 14:37:17 #include <cstdio> using namespace std; #define NODEREVERSE 2//标记是否交换子树的标志 #define BigNum 1100000000//一个比较大的数 struct Tnode{ int mark;//是否交换子树 int v,m,sz,delta;//v:节点的值 m:最小值 sz:子树的大小 delta:整个子树(不含自己)的增加量 Tnode *fa,*lc,*rc;//它的父亲,左、右儿子 int type();//它是右二子还是左儿子 }_no,*no;//用一个特殊的节点代替NULL Tnode tpool[200000];//分配内存用的 int tpc;//当前分配到得节点数 Tnode *root;//根指针 int Tnode::type(){ if (fa==no)return 0;//如果他没有父亲,返回0 if (fa->lc==this)return -1;//左儿子,返回-1 return 1;//右儿子 } inline Tnode* getNew(){Tnode *r; r=&(tpool[tpc++]);//得到新的内存单元 r->sz=1;r->mark=0;r->delta=0;//初始化 return r; } //NoMark函数用于释放一个节点的标记 void NoMark(Tnode *p){if (p==no)return;//它是空的 Tnode *t; if (p->mark&NODEREVERSE){//如果要交换子树 t=p->lc;p->lc=p->rc;p->rc=t;//交换 if (p->lc!=no)p->lc->mark^=NODEREVERSE;//下传标记 if (p->rc!=no)p->rc->mark^=NODEREVERSE; p->mark&=~NODEREVERSE;//释放标记 } if (p->delta){//增加量 if (p->lc!=no){//下传标记 p->lc->delta+=p->delta; p->lc->v+=p->delta; p->lc->m+=p->delta; } if (p->rc!=no){ p->rc->delta+=p->delta; p->rc->v+=p->delta; p->rc->m+=p->delta; } p->delta=0;//释放 } } void Correct(Tnode *p){//更新一个节点的sz与m p->sz=p->lc->sz+p->rc->sz+1; p->m=BigNum; p->m=p->v; if (p->lc->m+p->delta<p->m)p->m=p->lc->m+p->delta; if (p->rc->m+p->delta<p->m)p->m=p->rc->m+p->delta; } void zig(Tnode *p){//左旋 if (root==p->fa)root=p;//替代根 NoMark(p);//释放标记 p->fa->lc=p->rc;//处理它的右儿子 if (p->rc!=no)p->rc->fa=p->fa;//右儿子认父亲 p->rc=p->fa;//认自己的父亲为儿子 p->fa=p->fa->fa; if (p->fa!=no){//让自己的祖父认自己为儿子 if (p->rc->type()==1)p->fa->rc=p; else p->fa->lc=p; } p->rc->fa=p;//自己的父亲认自己为父亲 Correct(p->rc); Correct(p); } void zag(Tnode *p){//右旋 if (root==p->fa){ root=p; } NoMark(p); p->fa->rc=p->lc; if (p->lc!=no)p->lc->fa=p->fa; p->lc=p->fa; p->fa=p->fa->fa; if (p->fa!=no){ if (p->lc->type()==1){ p->fa->rc=p; } else { p->fa->lc=p; } } p->lc->fa=p; Correct(p->lc); Correct(p); } void Splay(Tnode *p){//伸展操作 while (p!=root){ if (p->fa==root){//自己是根了 if (p->type()==-1)zig(p); else zag(p); }else if (p->fa->type()==-1){//父亲是左儿子 if (p->type()==-1){//自己也是 zig(p->fa); zig(p); }else{//自己是右儿子 zag(p); zig(p); } }else{//父亲是右儿子 if (p->type()==-1){//自己是左儿子 zig(p); zag(p); }else{//自己是右儿子 zag(p->fa); zag(p); } } } } void Ins(int key,int v){//插入 Tnode *p,*q; if (root==no){//空的树,就新建一个 root=getNew(); root->v=root->m=v; root->fa=root->lc=root->rc=no; return; } p=root; while (1){ NoMark(p);//沿路释放标记 if (p->lc->sz>=key){//可以插入在左子树里 if (p->lc==no){//新建一个左子树 p->lc=getNew(); p->lc->v=p->lc->m=v; p->lc->fa=p;p->lc->lc=p->lc->rc=no; p=p->lc; break; } p=p->lc; }else{//走到右子树 key-=p->lc->sz+1;//重新计算key if (p->rc==no){//新建右子树 p->rc=getNew(); p->rc->v=p->rc->m=v; p->rc->fa=p;p->rc->lc=p->rc->rc=no; p=p->rc; break; } p=p->rc; } } for (q=p;q!=no;q=q->fa)Correct(q);//沿路更新 Splay(p);//伸展 } Tnode* Find(int key){//查找 Tnode *p; p=root; while (1){ NoMark(p);//沿路释放 if (p->lc->sz==key)break; if (p->lc->sz>key)p=p->lc; else{ key-=p->lc->sz+1; p=p->rc; } } return p; } void Del(int key){//删除 Tnode *p,*q,*oldroot; p=Find(key); if (p->lc==no && p->rc==no){ if (p->type()==-1)p->fa->lc=no; else p->fa->rc=no; p=p->fa; }else if (p->lc==no){ p->rc->fa=p->fa; if (p->type()==-1)p->fa->lc=p->rc; else p->fa->rc=p->rc; p=p->fa; }else{ oldroot=root; root=p->lc; q=Find(p->sz-1); Splay(q); root=oldroot; p->lc->rc=p->rc;p->rc->fa=p->lc; p->lc->fa=p->fa; if (p->type()==-1)p->fa->lc=p->lc; else p->fa->rc=p->lc; p=p->lc; } for (q=p;q!=no;q=q->fa)Correct(q); Splay(p); } Tnode* cutTree(int x,int y){//得到一个区间的子树 Tnode *px,*py; if (x && y<root->sz-1){ py=Find(y+1);Splay(py); px=Find(x-1);Splay(px); root=px->rc; Splay(py); root=px; return py->lc; }else if (x==0 && y<root->sz-1){ py=Find(y+1); Splay(py); return py->lc; }else if (x){ px=Find(x-1); Splay(px); return px->rc; }else return root; } void Add(int x,int y,int v){//增加 if (x>y)return; Tnode *p,*q; if (x==y){ p=Find(x);Splay(p); p->v+=v;Correct(p); return; } p=cutTree(x,y); p->v+=v;p->delta+=v; for (q=p;q!=no;q=q->fa)Correct(q); } void Reverse(int x,int y){//翻转 Tnode *p; if (x>=y)return; p=cutTree(x,y); p->mark^=NODEREVERSE; Splay(p); } void Revolve(int x,int y,int d){//移动 if (x>=y)return; d%=(y-x+1); if (!d)return; Tnode *p,*oldroot,*t,*l; p=cutTree(x,y); oldroot=root; root=p; t=Find(0);Splay(t); if (y==x+d){ l=t->lc;t->lc=t->rc;t->rc=l; root=oldroot; return; } l=Find(y-x-d); root=t->rc; Splay(l); t->lc=l->rc; l->rc->fa=t; l->rc=no; Correct(l); Correct(t); root=oldroot; } int getMin(int x,int y){//最小值 Tnode *p; if (x>y)return BigNum; if (x==y){ p=Find(x);Splay(p); return p->v; } p=cutTree(x,y); return p->m; } int res[100000],rc; int main() { no=&_no;no->mark=0;no->m=no->v=BigNum;no->sz=no->delta=0;no->fa=no->lc=no->rc=no; tpc=0; int N,x,y,d,M; char cmd[20]; scanf("%d",&N); root=no; for (int i=0;i<N;i++){ scanf("%d",&x); Ins(i,x); } scanf("%d",&M); rc=0; for (int i=0;i<M;i++){ scanf("%s",cmd); switch (cmd[0]){ case 'A': scanf("%d %d %d",&x,&y,&d); Add(x-1,y-1,d); break; case 'I': scanf("%d %d",&x,&d); Ins(x,d); break; case 'D': scanf("%d",&x); Del(x-1); break; case 'M': scanf("%d %d",&x,&y); res[rc++]=getMin(x-1,y-1); break; case 'R': if (cmd[3]=='E'){ scanf("%d %d",&x,&y); Reverse(x-1,y-1); }else if (cmd[3]=='O'){ scanf("%d %d %d",&x,&y,&d); Revolve(x-1,y-1,d); } break; } } for (int i=0;i<rc;i++)printf("%d\n",res[i]); getchar();getchar(); return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator