zoukankan      html  css  js  c++  java
  • hdu 4680 About set 小记(毕竟是一天的时光啊)

    Problem Description
    Today Zhanyl (sister Zhan as you know) receives a task about set operation. Although she is very good at this task, 
    but you know she is very lazy so that she wants you to help her write a program to complete this task. Surly
    Zhanyl is able to solve this question, but you know, she is just lazy ...
    Here is the problem, you are given n numbers, each number i has a value A i, initially they are in different set. 
    Following there are m operations/querys.
    The following is 5 possible kinds of oprations/querys:
    1 u v: Union the set u belongs to and the set v belongs to.
    2 u v: Delete u from its original set and add it to the set v belongs to.
    3 u x: change the value of u to x.  1<=x<=10 9
    4 u: query how many numbers you can choose most in set which u belongs to, so no three numbers can form a triangle.
    5 u l r: query the gcd of the numbers between [l,r] in the set u belongs to, if there is no number between [l,r],you can suppose the answer is -1.   1<=l<=r<=109
    Because Zhanyl is a good person, so she guarantee 1<=u,v<=n above.
    You need to tell Zhanyl the answer to each query.
     
    Input
    The first line of the input is a single integer T which is the number of test cases.Then comes the T test cases .
    For each test case, the first line contains two integer n and m, n is the number of set initially, m is the number 
    of operations/querys.
    Following line contains n integers, A 1, A 2, ... , A n, the value of i-th number.
    Following m lines, each line is a operation or query.

    Note that 1<=n,m<=10 5, 1<=A i<=10 9
     

     

    各种操作如上。
    大裸数据结构啊,比赛的时候想敲的,不过很长时间没写这种多
    颗树合并的题,而且有一个最关键的启发式合并的地方想歪了,认为复杂度不行,就没敲,现在想想还真是后悔,只怪自己的思维还不够严谨,要是在比赛中敲,不管能不能AC,都会比赛后敲来的激情啊。
    好歹花了一天时间,第一次全部手写splay树的所有函数,debug的时候过于自信就没去看那几个函数,而且还过了自己出的很多数据,后来看到了,就一点点改,一直到所有的bug都找到了(我认为的),交上去还是TLE,比较庆幸的是这次写没有像写10天津那个题一样,RE了好长一排(那是第一次写指针splay),很多结构调试起来还是轻松的,但是由于种种细节过多,导致我一开始就看出来的错误有一个地方没有修改好,然后就一直T。。
    一些花絮::
    TLE持续中。。。。。
    TLE持续中。。。。。
    实在是好忧桑啊。。。。。
    这日子没法过了。。。。。
    怎么办怎么办。。。。。。。。
    继续埋头看代码。。。。。
    找到了!!!!
    再来一发,还是TLE。。。。。
    MD,爆粗口了。。。。。
    好吧,先去赚点钱吧!!!!都是正事啊。。。
    教别人游泳的时候一直无法专心,,,,,明明没错啊,,,
    晚上回到寝室,杰哥帮忙跑了一发100000的数据,竟然跑不出来。。
    这不科学
    然后仔细一看,有个地方写傻了,,,,
    233333333333333333333333333333
    我乃绝世大sb,不能直视啊。。。
    然后怒交一发,AC了!!!!!!


    这个题思路很简单的,就按照题目告诉的模拟就好了,真正好的数据结构题不该是这种大裸的题吧,,,
    还是贴个代码吧。。。不过代码略微有些含蓄+混乱。。。切勿随意模仿
    /* **********************************************
    Author      : wuyiqi
    Created Time: 2013-8-16 8:24:44
    File Name   : hdu 4680.cpp
    *********************************************** */
    #pragma comment(linker,"/STACK:100000000,100000000")
    #include <cstring>
    #include <cstdio>
    #include <string>
    #include <iostream>
    using namespace std;
    #define L x->c[0]
    #define R x->c[1]
    #define KT  root->c[1]->c[0]
    const int  maxn = 300010;
    const int lim = 1000000000;
    inline int GCD(int a,int b) {
        if(a<0||a>lim) return b;
        if(b<0||b>lim) return a;
        return !b ? a : GCD(b,a%b);
    }
    struct node {
        struct node *c[2] , *fa;
        int id;
        int sz;
        int gcd;
        int val;
        int who;
        inline bool d() {
            return fa->c[0] == this;
        }
        inline void setc(int d,node *s) {
            c[d] = s;
            s->fa = this;
        }
        inline void up() {
            sz = c[0]->sz + c[1]->sz + 1;
            gcd = GCD(c[0]->gcd,c[1]->gcd);
            gcd = GCD(gcd,val);
        }
        inline void clear(node *null) {
            c[0] = c[1] = null;
        }
    }NODE[maxn] , *null = &NODE[0];
    node* Q[maxn];
    node* ID[maxn];
    int Type;
    int n;
    int top;
    struct _x_x_{
        int type;
        node* root;
        inline void Rotate(node *x,int f){
            node *y = x->fa;
            y->setc(!f,x->c[f]);
            x->fa = y->fa;
            if(y->fa != null) y->fa->setc(!y->d(),x);
            x->setc(f,y);
            y->up();
        }
        inline void Splay(node *x,node *goal) {
            while(x->fa!=goal) {
                if(x->fa->fa == goal) Rotate(x,x->d());
                else {
                    int f = x->fa->d();
                    x->d() == f ? Rotate(x->fa,f) : Rotate(x,!f);
                    Rotate(x,f);
                }
            }
            x->up();
            if(goal == null)  {
                root = x;
            }
        }
        inline void RTO(int k,node *goal) {
            node *x = root;
            while(L->sz + 1 != k) {
                if(k < L->sz + 1) x = L;
                else {
                    k -= L->sz + 1;
                    x = R;
                }
            }
            Splay(x,goal);
        }
        inline node* new_node(node *fa,int v) {
            node *x = &NODE[++top];
            x->id = top;
            x->c[0] = x->c[1] = null;
            x->sz = 1;
            x->val = v;
            x->gcd = v;
            x->fa = fa;
            ID[top] = x;
            return x;
        }
        inline void init(int v) {
            root = new_node(null,v);
            type = ++Type;
            root->who = type;
        }
        inline void Del_root() {
            node *t = root;
            if(t->c[1] != null) {
                root = t->c[1];
                RTO(1,null);
                root->c[0] = t->c[0];
                if(root->c[0] != null) 
                    root->c[0]->fa = root;
            } else  {
                root = root->c[0];
            }
            root->fa = null;
            if(root != null) root->up();
        }
        inline void Delete(node *x) {
            Splay(x,null);
            Del_root();
        }
        inline void Insert(node *x) {
            x->clear(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;
            }
            x->up();
        }
       inline  void Insert(int v) {
            node *x = new_node(null,v);
            insert(root,x);
            Splay(x,null);
            x->who = type;
        }
        inline void Change(int u,int v) {
            node *tmp = ID[u+2*n];
            Splay(tmp,null);
            Del_root();
            tmp->val = v;
            Insert(tmp);
        }
        node *find_succ(node *x,int v) {
            if(x == null) return x;
            if(x->val == v) return x;
            else if(x->val > v) {
                node *tmp = find_succ(x->c[0],v);
                return tmp == null ? x : tmp;
            }else {
                return find_succ(x->c[1],v);
            }
        }
        inline int find_succ(int v){ 
            node* tmp = find_succ(root,v);
            Splay(tmp,null) ;
            return tmp->val;
        }
        inline int Gao() {
            if(root->sz <= 4)  return root->sz - 2;
            RTO(2,null);
            int a = root->val;
            RTO(3,null);
            int b = root->val;
            int ans = 2;
            while(true){
                if(a + b > lim) break;
                int c = find_succ(a+b);
                if(c > lim || c == -1) break;
                a = b; b = c;
                ans++;
            }
            return ans;
        }
        void vist(node  *x) {
            if(x != null) {
                printf("节点 %2d:   左儿子: %2d    右儿子: %2d  sz:%2d val=%2d   gcd: %2d
    ",x->id,x->c[0]->id,x->c[1]->id,x->sz,x->val,x->gcd);
                vist(x->c[0]);
                vist(x->c[1]);
            } 
        }
        void debug() {
            puts("******************************************");
            vist(root); 
            puts("*****************************************");
        }
        node *Find_pre(node *x,int v) {
            if(x == null) return x;
            if(x->val < v) {
                node *tmp = Find_pre(x->c[1],v);
                return tmp == null ? x : tmp;
            } else {
                return Find_pre(x->c[0],v);
            }
        }
        node *Find_pre(int v) {
            node* tmp = Find_pre(root,v);
            Splay(tmp,null);
            return tmp;
        }
        node *Find_succ(node *x,int v) {
            if(x == null) return x;
            if(x->val > v) {
                node *tmp = Find_succ(x->c[0],v);
                return tmp == null ? x : tmp;
            } else {
                return Find_succ(x->c[1],v);
            }
        }
        node *Find_succ(int v) {
            node* tmp =  Find_succ(root,v);
            Splay(tmp,null);
            return tmp;
        }
        void Assert(string s) {
            cout<<s<<endl;
        }
        int Solve(int l,int r) {
            node *pre = Find_pre(l);
            node *succ = Find_succ(r);
            if(pre == null || succ == null) Assert("越界了");
            // printf("preid=%d succid=%d
    ",pre->id,succ->id);
            // pre : the first element strictly less than l
            // succ: the first element strictly bigger than r
            Splay(pre,null);
            Splay(succ,root);
            return KT->gcd;
        }
        void Merge(_x_x_ &tree) {
            int head = 0, tail = 0;
            tree.RTO(1,null);
            tree.RTO(tree.root->sz,tree.root);
            Q[++tail] = tree.KT;
            while(head < tail) {
                node *fr = Q[++head];
                if(fr->c[0] != null) Q[++tail] = fr->c[0];
                if(fr->c[1] != null) Q[++tail] = fr->c[1];
                Insert(fr);//此处吐血了一整天,上面的改回来了,这里却没改insert(root,fr);
                fr->who = type;
            }
            tree.KT = null;
            tree.root->c[1]->up();
            tree.root->up();
        }
    }spt[maxn];
    void prepare() {
        null->id = 0;
        null->c[0] = null->c[1] = null->fa = NULL;
        null->sz = null->val = 0;
        null->gcd = -1;
        Type = 0;
        top = 0;
    }
    int main()
    {
    //    freopen("input.txt","r",stdin);
    //    freopen("cmp.txt","w",stdout);
        int t,m,ca=1,op,u,v,l,r,x;
        scanf("%d",&t);
        while(t--) {
            prepare();
            scanf("%d%d",&n,&m);
            for(int i = 1; i <= n; i++){
                spt[i].init(-1);
                spt[i].Insert(lim+1);
            }
            for(int i = 1,a; i <= n; i++) {
                scanf("%d",&a);
                spt[i].Insert(a);
            }
            int tot = 0;
            printf("Case #%d:
    ",ca++);
            while(m--) {
                scanf("%d",&op);
                if(op == 1) {
                    scanf("%d%d",&u,&v); 
                    node *tmp1 = ID[u+2*n] , *tmp2 = ID[v+2*n];
                    int tree1 = tmp1->who;
                    int tree2 = tmp2->who;
                    if(tree1 == tree2) continue;
                    int sz1 = spt[tree1].root->sz;
                    int sz2 = spt[tree2].root->sz;
                    if(sz1 > sz2) {
                        spt[tree1].Merge(spt[tree2]);
                    } else {
                        spt[tree2].Merge(spt[tree1]);
                    }
    				//      if(spt[tree1].root->sz < 2 || spt[tree2].root->sz < 2){
    				//           return 0;
    				//            break;
    				//      }
    				//                spt[tree1].debug();
                } else if(op == 2) {
                    scanf("%d%d",&u,&v);
                    node *tmp1 = ID[u+2*n] , *tmp2 = ID[v+2*n];
                    int tree1 = tmp1->who;
                    int tree2 = tmp2->who;
                    // spt[tree1].debug(); spt[tree2].debug();
                    spt[tree1].Delete(tmp1);
                   // if(spt[tree2].root->sz < 2) return 0;
                    spt[tree2].Insert(tmp1);
                    // spt[tree1].debug(); spt[tree2].debug();
                } else if(op == 3) {
                    scanf("%d%d",&u,&x);
                    node *tmp = ID[u+2*n];
                    int tree = tmp->who;
                    spt[tree].Change(u,x);
                }  else if(op == 4) {
                    scanf("%d",&u);
                    node *tmp = ID[u+2*n];
                    int tree = tmp->who;
                    printf("%d
    ",spt[tree].Gao());
                } else {
                    scanf("%d%d%d",&u,&l,&r);
                    node *tmp = ID[u+2*n];
                    int tree = tmp->who;
    				   //  printf("id=%d tree=%d
    ",tmp->id,tree);
                    printf("%d
    ",spt[tree].Solve(l,r));
                }
            }
        }
        return 0;
    }


  • 相关阅读:
    高等数学(6) 无穷小和无穷大
    高等数学(5) 函数的极限
    高等数学(4) 数列与数列极限
    实时音视频互动系列(下):基于 WebRTC 技术的实战解析
    实时音视频互动系列(上):又拍云UTUN网络详解
    免费SSL&付费SSL证书,该如何选择?
    直播卡顿原因详解及优化
    实战解析 | 同步音视频解决方案
    从Html5直播到互动直播,看直播协议的选择
    如何将HLS延时缩短至4秒,HLS+技术详解
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3265325.html
Copyright © 2011-2022 走看看