hdu 1007 最近點對問題(Splay解法)

爲什麼要寫這個題、、經典啊,當然,別以爲我用分治做的,不過主要思想還是那神奇的六個點共存(一個h*2h的矩形中最多能放下多少個點使得兩兩距離不超過h)

其實我是在這裏看到的

http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=lineSweep

排個序,然後掃描過去,每次確定Y的範圍,暴力找每個點(其實這是O(1)的)

蠻不錯的哦。

寫完後發現比分治寫的快了好多啊,估計是我不會寫分治吧T_T,總之,現在跑到了rank 4了。。。

數據結構就是這樣的直接啊!

/* **********************************************
Author      : wuyiqi
Created Time: 2013-8-24 12:54:35
File Name   : ruocai.cpp
*********************************************** */
#include <cstdio>
#include <cmath>
#include <stack>
#include <algorithm>
using std::stack;
    using std::pair;
    using std::make_pair;
#define L x->c[0]
#define R x->c[1]
#define KT root->c[1]->c[0]
const int maxn = 200010;
struct node{
    node *c[2] , *fa;
    int id,sz;
    double val,x;
    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;
    }
}NODE[maxn],*null=&NODE[0];
node *ID[maxn];
int top;
struct Splay_tree{
    node *root;
    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();    
    }    
    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;    
        }    
    }    
    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);    
    }    
    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();    
    }    
    node* new_node(int id,double x,double y) {
        node* tmp = &NODE[++top];
        tmp->fa = null;
        tmp->val = y;
        tmp->x = x;
        tmp->sz = 1;
        tmp->id = top;
        tmp->c[0] = tmp->c[1] = null;
        ID[id] = tmp;
        return tmp;
    }
    void insert(int id,double x,double y) {
        node *tmp = new_node(id,x,y);
        insert(root,tmp);
    }
    void init() {
        root = null;
    }
    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();    
    }    

    void Del(node *tmp) {
        Splay(tmp,null);
        Del_root();
    }
    node* find_pre(node *x,double v) {
        if(x == null) return null;
        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_succ(node *x,double v) {
        if(x == null) return null;
        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);
        }
    }
    void search(double a,double b,double &ans,node* x){
        if(x == null) return ;
        double  c = x->x , d = x->val;
        double cost = sqrt((a-c)*(a-c) + (b-d)*(b-d));
        if(cost  < ans) ans = cost;
        if(x->c[0] != null) search(a,b,ans,x->c[0]);
        if(x->c[1] != null) search(a,b,ans,x->c[1]);
    }
    void gao(double x,double y,double &ans) {
        node *pre = find_pre(root,y-ans) ;
        node *succ = find_succ(root,y+ans);
        if(pre == null || succ == null) while(1);
        Splay(pre,null);
        Splay(succ,root);
        search(x,y,ans,KT);
    }
    void vist(node *x) {
        if(x!=null) {
            printf("%d x = %lf y = %lf lson=%d rson=%d\n",x->id,x->x,x->val,x->c[0]->id,x->c[1]->id);
            if(x->c[0]!=null) vist(x->c[0]);
            if(x->c[1]!=null) vist(x->c[1]);
        }
    }
    void debug(){
        puts("*******");
        vist(root);
        puts("*****");
    }
}spt;
void prepare() {
    null->id = 0;
    null->c[0] = null->c[1] = null->fa = NULL;
    null->sz = null->val = 0;
    top = 0;
}
double x[maxn] , y[maxn];
bool by_x(int a,int b) {
    return x[a] > x[b];
}
int id[maxn];
double sqr(double a) {  return a * a; }
int main()
{
    int n;
    while(scanf("%d",&n),n) {
        prepare();
        spt.init();
        for(int i = 0; i < n; i++) {
            id[i] = i;
            scanf("%lf%lf",&x[i],&y[i]);
        }
        if(n == 1){
            puts("0.00");
            continue;
        }
        std::sort(id,id+n,by_x);
        spt.insert(0,-1e100,-1e100);
        spt.insert(0,-1e100,1e100);
        double ans = 1e50 ;
        int pt = 0;
        for(int i = 0; i < n; i++) {
            if(ans == 0) break;
            while(pt < i && x[id[pt]] > x[id[i]] + ans ) {
                if(spt.root->sz == 2) break;
                spt.Del(ID[id[pt]]);
                pt++;
            }
            if(spt.root->sz == 2) {
                spt.insert(id[i],x[id[i]],y[id[i]]);
            } else {
                spt.gao(x[id[i]],y[id[i]],ans);
                spt.insert(id[i],x[id[i]],y[id[i]]);
            }
        }
        printf("%.2f\n",ans*0.5);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章