zoukankan      html  css  js  c++  java
  • FJoi2017 1月21日模拟赛 comparison(平衡树+thita重构)

    题目大意:

    经黄学长指出,此题原题出自2014湖北省队互测 没有人的算术

    规定集合由二元组(A,B)构成,A、B同时也是两个这样的集合,即A、B本身也是二元组

    规定二元组S为严格最小集合,S=(S,S),规定T为严格最大集合T=(T,T)

    刚开始我们有两个集合S和T,即全局最小集合和全局最大集合,编号分别为0,n+1

    下面我们规定集合的比较规则,是递归定义的

    我们称集合X(X1,X2)等于Y(Y1,Y2)当且仅当

    X1=Y1 并且 X2=Y2

    我们称集合X(X1,X2)小于Y(Y1,Y2)当且仅当

    1.X1<Y1

    2.X1==Y1 且 X2<Y2

    现在有n个操作:

    1.将集合u、v合并为新二元组集合X(u,v)

    2.输出所有小于或等于X的集合数量

    输入

    第一行一个整数n,代表有n个操作

    下面n行,每行2个数u、v代表将集合u、v组合成新的集合

    输出

    共n行,每行一个整数,代表当前全集中小于或等于当前新生成集合的数量

    样例输入

    30
    31 0
    0 31
    0 1
    3 3
    3 4
    4 2
    3 4
    31 3
    2 2
    5 3
    9 4
    8 1
    9 12
    13 5
    13 12
    13 0
    3 12
    4 3
    15 18
    16 16
    11 5
    14 17
    9 20
    20 18
    16 10
    31 24
    20 7
    7 5
    14 21
    24 4

    样例输出

    2
    2
    2
    4
    5
    6
    6
    9
    7
    9
    10
    11
    11
    12
    13
    12
    7
    9
    17
    17
    14
    19
    13
    22
    19
    27
    23
    12
    23
    27

    Solution

    orz神犇wwx

    法一:

    先考虑最暴力的做法,那就是O(n*n)的递归比较

    得分10

    法二:

    考虑将集合维护成一个有序序列,用插入排序O(n)解决一个点的插入,就可以O(1)得出答案,比较就是比数组下标就行了哦

    得分30

    法三:

    显然可以用平衡树维护大小关系嘛,把原来数组变成一个映射,将下标映射到区间[0,oo)上记为Val,其中S取0,T去oo,插入时,若集合X大小在A、B间,则Val(X)=(Val(A)+Val(B))/2

    那么,每次插入后为了维护Val,就要重构遍平衡树

    得分100

    下面是标解

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    #define MaxN 50010
    #define MaxBuf 1<<22
    #define inf LONG_LONG_MAX/2
    #define mid ((l>>1)+(r>>1)+(l&r&1))
    #define RG register
    #define inline __inline__ __attribute__((always_inline))
    #define Blue() ((S==T&&(T=(S=B)+fread(B,1,MaxBuf,stdin),S==T))?0:*S++)
    
    char B[MaxBuf],*S=B,*T=B;
    
    template<class Type>inline void Rin(RG Type &x){
        x=0;RG int c=Blue();RG bool b=false;
        for(;c<48||c>57;c=Blue())
            if(c==45)b=true;
        for(;c>47&&c<58;c=Blue())
            x=(x<<1)+(x<<3)+c-48;
        if(b)x=-x;
    }
    
    int n,ans;
    struct Treap{
    #define L long long
        struct Nt{
            Nt *ch[2],*s1,*s2;
            int size,k;
            L v;
    
            inline void pud() {size=ch[0]->size+ch[1]->size+1;}
        }pool[MaxN],*null,*root,*Re_p;
    
        L Re_s,Re_t;
    
        inline void rotate(RG Nt *&o,RG bool d){
            RG Nt *k=o->ch[d];
            o->ch[d]=k->ch[!d];
            k->ch[!d]=o;
            o->pud();
            k->pud();
            o=k;
        }
    
        void insert(RG Nt *&o,RG Nt *p,RG L l,RG L r){
            if(o==null){
                    o=p;
                p->k=rand()*2333+rand(); p->v=mid; p->size=1;
                printf("%d
    ",ans);
                return;
            }
            RG bool d=(p->s1->v > o->s1->v) || (p->s1->v == o->s1->v && p->s2->v >= o->s2->v);
            d? (ans+=o->ch[0]->size+1,insert(o->ch[1],p,o->v+1,r)):(insert(o->ch[0],p,l,o->v-1));
            if(o->ch[d]->k < o->k)rotate(o,d),Re_p=o,Re_s=l,Re_t=r;
            o->pud();
        }
    
        void Relabel(Nt *o,L l,L r){
            if(o==null)return;
            o->v=mid;
            Relabel(o->ch[0],l,o->v-1);
            Relabel(o->ch[1],o->v+1,r);
        }
    public:
        void init(){
            root=null=pool+n+2;
            null->ch[0]=null->ch[1]=null;
            pool->v=0;
            (pool+n+1)->v=inf+1;
        }
    
        inline void insert(RG int cnt,RG int u,RG int v){
            ans=2;
            pool[cnt].s1=pool+u;
            pool[cnt].s2=pool+v;
            pool[cnt].ch[0]=pool[cnt].ch[1]=null;
            Re_p=null;
            insert(root,pool+cnt,1,inf);
            Relabel(Re_p,Re_s,Re_t);
        }
    }RT;
    
    #define set_file(File) {freopen(#File".in","r",stdin); freopen(#File".out","w",stdout);}
    #define close_file() {fclose(stdin); fclose(stdout);}
    
    int main(){
        srand('K'+'a'+'i'+'b'+'a');
    
        set_file(comparison);
    
        Rin(n); RT.init();
        for(RG int i=1,u,v;i<=n;i++){
            Rin(u),Rin(v);
            RT.insert(i,u,v);
        }
    
        close_file();
    
        return 0;
    }
  • 相关阅读:
    BZOJ1054|HAOI2008移动玩具|广搜
    tarjan算法
    BJOJ2190|SDOI仪仗队|数论
    POJ2975|Nim|博弈论
    POJ1740|A NEW STONE GAME|博弈论
    python 单例模式
    linux 根据服务名称批量杀死进程
    python 任务计划
    python偏函数
    安装scrapy框架
  • 原文地址:https://www.cnblogs.com/keshuqi/p/6337701.html
Copyright © 2011-2022 走看看