[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

 

你可能感兴趣的:(数据结构)