hdu4680 About set ——-splay

來源:互聯網
上載者:User

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4680

總體思路:初始化n棵splay樹,合并的時候需要用啟發學習法合并最佳化一下,前三個操作照做就行,第四個關於三角形的詢問需要西安判斷當前splay樹上有沒有3個節點,多餘三個的話就先枚舉最小的邊a和次小的邊b,然後尋找a+b的後繼c,找到的話答案加一,然後a = b,b=c遍曆一遍就行了,第五個關於GCD的操作就很簡單了,把[l,r]區間提取出來直接輸出GCD就行。下面上代碼:


#include<cstdio>#include<iostream>#include<cstring>#define L x->c[0]#define R x->c[1]#define KT root->c[1]->c[0]using namespace std;const int maxn = 300010;const int inf = 1000000007;int n,Type;int gcd(int a,int b){    if(a<0||a>=inf) return b;    if(b<0||b>=inf) return a;    return b == 0?a:gcd(b,a%b);}struct Node//id表示節點編號,g表示gcd,who表示節點屬於哪個splay樹{    struct Node *c[2],*fa;    int id,size,g,val,who;}S[maxn],*null = &S[0];Node* Q[maxn];Node* ID[maxn];int scnt;struct snode{    int type;    Node*root;    inline Node *NewNode(int value,Node *p)//建立節點    {        Node *e = S+(++scnt);        e->val = value;        e->id = scnt;        e->size = 1;        e->fa = p;        e->g = value;        e->c[0] = e->c[1] = null;        ID[scnt] = e;        return e;    }    inline void Update(Node *p)//更新節點資訊    {        p->size = p->c[0]->size+p->c[1]->size+1;        p->g = gcd(p->c[0]->g,p->c[1]->g);        p->g = gcd(p->val,p->g);    }    inline void Rotate(Node *x,int k)//旋轉    {        Node *y=x->fa;        y->c[k]=x->c[!k];        y->c[k]->fa=y;        x->fa=y->fa;        if(y->fa->c[0]==y)            y->fa->c[0]=x;        else            y->fa->c[1]=x;        y->fa=x;        x->c[!k]=y;        Update(y);        Update(x);        if(root==y) root=x;    }    inline void Splay(Node *x,Node *y)//伸展    {        while(x->fa!=y)        {            if(x->fa->fa==y)            {                if(x->fa->c[0]==x)                    Rotate(x,0);                else                    Rotate(x,1);            }            else if(x->fa->fa->c[0]==x->fa)            {                if(x->fa->c[0]==x)                    Rotate(x->fa,0),Rotate(x,0);                else                    Rotate(x,1),Rotate(x,0);            }            else            {                if(x->fa->c[1]==x)                    Rotate(x->fa,1),Rotate(x,1);                else                    Rotate(x,0),Rotate(x,1);            }        }        Update(x);    }    inline void Select(int k,Node *y)//旋轉第k個節點至y下方    {        Node *x=root;        while(k!=x->c[0]->size+1)        {            if(k<=x->c[0]->size)                x=x->c[0];            else            {                k-=x->c[0]->size+1;                x=x->c[1];            }        }Splay(x,y);    }    inline void Init(int v)//初始化    {        root = NewNode(v,null);        type = ++Type;        root->who = type;    }    inline void Delete(Node *x)//刪除節點    {        Splay(x,null);        Node *t = root;        if(t->c[1]!=null)        {            root = t->c[1];            Select(1,null);            root->c[0] = t->c[0];            if(root->c[0]!=null)                root->c[0]->fa = root;        }        else        {            root = t->c[0];        }        root->fa = null;        if(root!=null)Update(root);    }    inline void Insert(Node *x)//插入節點    {        x->c[0] = x->c[1] = null;        insert(root,x);        Splay(x,null);        x->who = type;    }    inline void insert(Node* &x,Node* y)    {        if(x == null)        {            x = y;            return;        }        if(y->val<=x->val)        {            insert(x->c[0],y);            x->c[0]->fa = x;        }        else        {            insert(x->c[1],y);            x->c[1]->fa = x;        }        Update(x);    }    inline void Change(Node* tmp,int v)//改變節點值    {        Delete(tmp);        tmp->val = v;        Insert(tmp);    }    inline Node *FindSucc(Node *x,int v,int opt)    {        if(x == null)return x;        if(x->val == v&&opt)return x;        else if(x->val>v)        {            Node *tmp = FindSucc(x->c[0],v,opt);            return tmp == null?x:tmp;        }        else        {            return FindSucc(x->c[1],v,opt);        }    }    inline Node *FindSucc(int v,int opt)//尋找v的後繼,opt為1表示後繼可以等於v,否則不可以等於    {        Node *tmp = FindSucc(root,v,opt);        Splay(tmp,null);        return tmp;    }    inline Node *FindPre(Node *x,int v)    {        if(x == null)return x;        if(x->val<v)        {            Node *tmp = FindPre(x->c[1],v);            return tmp == null?x:tmp;        }        else return FindPre(x->c[0],v);    }    inline Node *FindPre(int v)//尋找前驅    {        Node* tmp = FindPre(root,v);        Splay(tmp,null);        return tmp;    }    inline void Merge(snode &tree)//合并    {        int head,tail;        head = tail = 0;        tree.Select(1,null);        tree.Select(tree.root->size,tree.root);        Q[++tail] = tree.KT;        while(head<tail)        {            Node* f = Q[++head];            if(f->c[0]!=null)Q[++tail] = f->c[0];            if(f->c[1]!=null)Q[++tail] = f->c[1];            Insert(f);            f->who = type;        }        tree.KT = null;        tree.Update(tree.root->c[1]);        tree.Update(tree.root);    }    inline int SolveTri()//查詢4    {        if(root->size<=4)return root->size-2;        Select(2,null);        int a = root->val;        Select(3,null);        int b = root->val;        int ans = 2;        while(true)        {            if(a+b>=inf)break;            int c = FindSucc(a+b,1)->val;            if(c>=inf||c == -1)break;            a = b;            b = c;            ans++;        }        return ans;    }    inline int SolveGcd(int l,int r)//查詢5    {        Node *pre = FindPre(l);        Node *succ = FindSucc(r,0);        Splay(pre,null);        Splay(succ,root);        return KT->g;    }    void vist(Node *x)    {        if(x != null)        {            printf("root %2d:  left-son: %2d    right-son: %2d  size:%2d val=%2d   gcd: %2d\n",x->id,x->c[0]->id,x->c[1]->id,x->size,x->val,x->g);            vist(x->c[0]);            vist(x->c[1]);        }    }    void debug()    {        puts("******************************************");        vist(root);        puts("*****************************************");    }}spt[maxn];void prepare(){    null->id = 0;    null->c[0] = null->c[1] = null->fa = NULL;    null->size = null->val = 0;    null->g = -1;    Type = 0;    scnt = 0;}int main(){    int t,n,m,a,u,v,op,l,r,x,cas = 1;    scanf("%d",&t);    while(t--)    {        prepare();        printf("Case #%d:\n",cas++);        scanf("%d%d",&n,&m);        for(int i = 1;i<=n;i++)        {            spt[i].Init(-1);            Node *tmp = spt[i].NewNode(inf,null);            spt[i].Insert(tmp);        }        for(int i = 1;i<=n;i++)        {            scanf("%d",&a);            Node *tmp = spt[i].NewNode(a,null);            spt[i].Insert(tmp);        }        int tot = 0;        while(m--)        {            scanf("%d",&op);            if(op == 1)            {                scanf("%d%d",&u,&v);                Node *t1 = ID[u+2*n];                Node *t2 = ID[v+2*n];                int tree1 = t1->who;                int tree2 = t2->who;                if(tree1 == tree2)continue;                int size1 = spt[tree1].root->size;                int size2 = spt[tree2].root->size;                if(size1>size2)spt[tree1].Merge(spt[tree2]);                else spt[tree2].Merge(spt[tree1]);            }            else if(op == 2)            {                scanf("%d%d",&u,&v);                Node *t1 = ID[u+2*n];                Node *t2 = ID[v+2*n];                int tree1 = t1->who;                int tree2 = t2->who;                spt[tree1].Delete(t1);                spt[tree2].Insert(t1);            }            else if(op == 3)            {                scanf("%d%d",&u,&x);                Node *tmp = ID[u+2*n];                int tree = tmp->who;                spt[tree].Change(tmp,x);            }            else if(op == 4)            {                scanf("%d",&u);                Node *tmp = ID[u+2*n];                int tree = tmp->who;                printf("%d\n",spt[tree].SolveTri());            }            else            {                scanf("%d%d%d",&u,&l,&r);                Node *tmp = ID[u+2*n];                int tree = tmp->who;                printf("%d\n",spt[tree].SolveGcd(l,r));            }        }    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.