Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

精诚所至金石为开,发帖向路过的大牛们求救!

Posted by AllwaysLoser at 2009-05-01 14:03:56 on Problem 3580 and last updated at 2009-05-01 14:18:19
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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator