zoukankan      html  css  js  c++  java
  • [HNOI2004]宠物收养所 数据结构题

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1208

    题意:  中文题就不说了,都能看明白

    解法: 数据结构题,应该使用一个BST类型的数据结构来实现,bst,treap,avl,splay,sbt,等等都可以。

          我的解法是维护两个 spaly tree,A表示宠物,B表示收养者,

      对于 a = 0, 添加宠物时, 首先检查 B是否为空, 若执行 A.insert( a ), 否则,调用方法 B.deal( a ).

      deal( val ) 的思路:  若B中原本就有val值,则花费为0,直接删除key[x]=val的节点。 否则插入一个值为val的节点,

    然后将其 splay( x, 0 ), 旋转到根, 然后找其 第一个比其小,与第一个比其大的,比较一下,小于或等于取左(题目要求),然后删除

    选定的 l, 或者 r.   这时候还要删除多插入的 key[x] = val 的 x.  

      我是通过写了一个 remove( x ) 方法, 具体思路是,将其通过 splay( x, 0 ) 旋转到根,找其左或右第一个子节点 lch or rch, 则

    lch or rch 存在则,必定 lch 无右孩子,rch 无左孩子,随便取一个替代x即可,处理下 指针关系即可。注意分情况考虑,因为lch or rch

    可能不存在,此时需要分情况处理。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int mod = (int)1e6;
    typedef long long LL;
    const int N = 80100;
    struct Splay{
        int ch[N][2], pre[N], sz[N];
        LL key[N];
        int rt, top;
        void rotate(int x,int d){
            int y = pre[x];
            ch[y][d^1] = ch[x][d];
            if( ch[x][d] ) pre[ch[x][d]] = y;
            if( pre[y] ) ch[pre[y]][ ch[pre[y]][1]==y ] = x;
            pre[x] = pre[y];
            ch[x][d] = y;
            pre[y] = x;
            push_up(y);
        }
        void splay(int x,int goal){
            while( pre[x] != goal ){
                int y = pre[x];
                if( pre[y] == goal ) rotate( x, ch[y][0]==x );
                else{
                    int z = pre[y];
                    int d1 = ch[z][0]==y, d2 = ch[y][0]==x;
                    if( d1 == d2 ) rotate(y,d1),rotate(x,d2);
                    else rotate(x,d2), rotate(x,d1);
                }    
            }    
            if(goal == 0) rt = x;    
            push_up(x);
        } 
        void push_up(int x){
            if( x ) sz[x] = 1+sz[ ch[x][0] ]+sz[ ch[x][1] ];    
        }    
        void NewNode(int &x,LL c,int f){
            x = ++top;
            ch[x][0]=ch[x][0]=0;
            pre[x]=f, key[x]=c, sz[x] = 1;
        }    
        void init(){
            ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;
            rt = top = 0;
        }
        void insert(int x, LL val, int f){
            if( x == 0 ){ // if tree is empty
                NewNode(rt,val,0);    
                return;    
            }                
            int d = val > key[x];
            if( ch[x][d] != 0 ) insert( ch[x][d], val, x );    
            else{
                NewNode( ch[x][d], val, x );
                splay( ch[x][d], 0 );    
            }
            push_up(x);    
        }
        int find(LL val){
            int x = rt;
            while(x){
                if( key[x] == val ) return x;
                x = ch[x][ val > key[x] ];
            }    
            return 0;    
        }    
        void remove(int x){
            splay(x,0);
            if( ch[x][0] ){
                int y = ch[x][0];
                while( ch[y][1] ) y = ch[y][1];
                splay( y, x );
                ch[y][1] = ch[x][1]; pre[y] = pre[x];
                if( ch[x][1] ) pre[ ch[x][1] ] = y;
                if( pre[x] ) ch[pre[x]][ch[pre[x]][1]==x] = y;
                if( x == rt ) rt = y;
                push_up(y);    
            }
            else if( ch[x][1] ){
                int y = ch[x][1];    
                while( ch[y][0] ) y = ch[y][0];
                splay( y, x );
                ch[y][0] = ch[x][0]; pre[y] = pre[x];
                if( ch[x][0] ) pre[ ch[x][0] ] = y;
                if( pre[x] ) ch[pre[x]][ch[pre[x]][1]==x] = y;
                if( x == rt ) rt = y;
                push_up(y);    
            }
            else rt = 0;
        }     
        LL deal(LL val){
            int x = find(val); LL sum;
            //printf("Find: x = %d\n", x );
            if( x ){ remove(x);    sum = 0; }
            else{
            //    printf("Deal pre:\n"); print(rt);    
                insert( rt, val, 0 );
            //    printf("Deal:\n"); print(rt);
            
                x = find(val);
                splay(x,0);    
                int l = ch[x][0], r = ch[x][1];
                while( l && ch[l][1] ) l = ch[l][1];
                while( r && ch[r][0] ) r = ch[r][0];
            //    printf("l = %d, r = %d\n", l, r );            
                if( l && r ){
                    if( (val-key[l]) <= (key[r]-val) )
                        sum = val-key[l], remove(l);    
                    else
                        sum = key[r]-val, remove(r);    
                }
                else if( l ){ sum = val-key[l], remove(l); }
                else if( r ){ sum = key[r]-val, remove(r); }
                remove(x);    
            }    
            return sum;    
        }
        
        void print(int x){
            if( x == 0 ){ printf("Empty!\n"); return; }
            if( ch[x][0] ) print( ch[x][0] );
            printf("x=%d, lch=%d, rch=%d, pre=%d, sz=%d, key=%lld\n",
                    x,ch[x][0],ch[x][1],pre[x],sz[x],key[x]);
            if( ch[x][1] ) print( ch[x][1] );
        }
    }A, B;
    
    int main(){
        int n;
        while( scanf("%d", &n) != EOF){
            int a; LL b;
            LL res = 0;    
            A.init(); B.init();    
            for(int i = 0; i < n; i++){
                scanf("%d%lld", &a, &b);    
                if( a == 0 ){ // dog
                    if( B.sz[ B.rt ] == 0 ) A.insert(A.rt,b,0);    
                    else res += B.deal(b);    
            ///        printf("A:\n"); A.print( A.rt );    
            //        printf("B:\n"); B.print( B.rt );    
                }
                else{ // people
                    if( A.sz[ A.rt ] == 0 ) B.insert(B.rt,b,0);
                    else res += A.deal(b);
            //        printf("A:\n"); A.print( A.rt );    
            //        printf("B:\n"); B.print( B.rt );    
                }
                res %= mod;    
            }
            printf("%lld\n", res );    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    jQuery图片翻转弹出动画特效
    HTML5来了,7个混合式移动开发框架
    10款很好用的 jQuery 图片滚动插件
    JS图片自动和可控的轮播切换特效
    CSS3扇形动画菜单 鼠标滑过扇形展开动画
    css里面的几个你不知道的属性
    JS判断是否是微信打开页面
    js的escape()、encodeURI()、encodeURIComponent()区别详解
    使用HTML5的十大原因
    Hybrid App开发 四大主流移平台分析
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/3078601.html
Copyright © 2011-2022 走看看