acm 各种树的合集

线段树:http://blog.csdn.net/metalseed/article/details/8039326
二叉搜索树: http://blog.csdn.net/npy_lp/article/details/7426431
AVL搜索树:http://wenku.baidu.com/link?url=fDbBrwiRN7_SRbcyOm07616IOckh3iYc5POssnQkgSeSscSD7_hjRSMRZpwiLamclVeu3F8xitxBbDCxecFVTbjQhhZYQczMTF6Sd-KmrHi
红黑树:http://blog.csdn.net/eric491179912/article/details/6179908
伸展树:http://www.cnblogs.com/kernel_hcy/archive/2010/03/17/1688360.html
Treap树堆:http://www.cnblogs.com/shuaiwhu/archive/2012/05/06/2485894.html
SBT:http://www.cnblogs.com/zgmf_x20a/archive/2008/11/14/1333205.html
跳跃表:http://dsqiu.iteye.com/blog/1705530
左偏树:图解:http://www.cppblog.com/guogangj/archive/2009/10/30/99833.html
实现:http://blog.csdn.net/theprinceofelf/article/details/7247454
主席树:http://blog.csdn.net/sprintfwater/article/details/9162041
kd-tree:http://blog.csdn.net/yapian8/article/details/40372967

kd-tree 题目:


Description

Given n points in 2-dimensional plane. For each point p, we can draw a circle with center p and radius r (r is the 

distance between point p and the kth nearest point (except p) of p). Now we need to select m points from the n 

points, such that the m circles generated by the selected m points are the largest m ones. If there are two circles

 which have the same radius, then select the one with smaller id. Please calculate the area of the union region 

of the m circles.

Note 1: The distance we use in this problem is the Euclidean distance, that is to say, if there are two points 

p(x1, y1) and q(x2, y2), then the distance of p and q is:

dis(p,q)=dis(q,p)=sqrt( (x1-x2)^2 + (y1-y2)^2 );

Note 2: If point p is input earlier than point q, then we say point p has a smaller id.

Input

The first line contains only one positive integer T (T <= 15), representing there are T cases below.

For each case, the first line contains two positive integer n, m (2 <= n <= 100000, 1 <= m <= 1000, m <= n), 

representing the number of points in 2dimensional plane and the number of points we need to select. 

Then n lines, each line contains three integers x, y, k (-5000 <= x, y <= 5000, 1 <= k <= 10, k < n), representing 

the information of one point: (x, y) is the coordinate, and the meaning of k is given in problem description. 

We guarantee that all points are distinct.

Output

Each case a line. For each case, print the area of the union of the m circles with 2 digits after decimal point.

Sample Input

1

3 3

0 0 2

1 0 2

2 0 1

 

Sample Output

14.30

AuthorHu Fan

 

</pre>代码:<p><pre name="code" class="cpp">#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 100010;
const int maxr = 1010;
const double eps = 1e-8;
const double EPS = 1e-5;
#define Equ(a,b) ((fabs((a)-(b)))<(eps))
#define Less(a,b) (((a)-(b))<(-(eps)))
#define LessEqu(a,b) (((a)-(b))<(eps))
#define More(a,b) (((a)-(b))>(eps))
#define MoreEqu(a,b) (((a)-(b))>(-(eps)))


int n, m;
typedef pair<double, double> PDD;
double x[maxr], y[maxr], r[maxr];
double nx[maxr], ny[maxr], nr[maxr];
double xl[maxr], xr[maxr];
int s[maxr];


struct Point {
    int x[2];
    int k;
    int dis;
    int id;
    int distance(const Point& a) const {
        int res = 0;
        for(int i = 0; i < 2; i++) {
            res += (x[i] - a.x[i]) * (x[i] - a.x[i]);
        }
        return res;
    }
    bool operator < (const Point& a) const {
        return dis < a.dis;
    }
}ps[maxn], qs[maxn], tempp;


bool cmp_dis(const Point& a, const Point& b) {
    if(a.dis != b.dis) return a.dis > b.dis;
    else return a.id < b.id;
}


int Div[maxn];
int cmpdiv;
priority_queue <Point> q;


bool cmp(const Point& a, const Point& b) {
    return a.x[cmpdiv] < b.x[cmpdiv];
}


void Build_kdTree(int l, int r, Point* p, int depth) {
    if(l > r) return;
    int mid = (l + r) >> 1;
    Div[mid] = depth % 2;
    cmpdiv = Div[mid];
    nth_element(p + l, p + mid, p + r + 1, cmp);
    Build_kdTree(l, mid - 1, p, depth + 1);
    Build_kdTree(mid + 1, r, p, depth + 1);
}


void Query(int l, int r, Point* p, Point a) {
    if(l > r) return;
    int mid = (l + r) >> 1;
    tempp = p[mid];
    tempp.dis = a.distance(tempp);
    if(tempp.dis != 0) {
        if(q.size() < a.k) q.push(tempp);
        else if(tempp.dis < q.top().dis) {
            q.pop();
            q.push(tempp);
        }
    }
    int d = a.x[Div[mid]] - tempp.x[Div[mid]];
    int l1 = l, r1 = mid - 1;
    int l2 = mid + 1, r2 = r;
    if(d > 0) l1 ^= l2 ^= l1 ^= l2, r1 ^= r2 ^= r1 ^= r2;
    Query(l1, r1, p, a);
    if(q.size() < a.k || d * d < q.top().dis) {
        Query(l2, r2, p, a);
    }
}


inline bool cmp1(int a,int b) {
    if(Equ(x[a] - r[a], x[b] - r[b])) return Less(x[a] + r[a], x[b] + r[b]);
    return Less(x[a] - r[a], x[b] - r[b]);
}
inline bool cmp0(int a, int b) {
    return More(r[a], r[b]);
}
int L, R;
PDD se[maxr];
inline double f(double v) {
    int sz = 0, i, j;
    double ret = 0.0;
    for(i = L; i < R; ++i) {
        if(LessEqu(v, xl[i]) || MoreEqu(v, xr[i])) continue;
        j = s[i];
        double d = sqrt(r[j]- (v - x[j]) * (v - x[j]));
        se[sz].first = y[j] - d;
        se[sz].second = y[j] + d;
        ++sz;
    }
    sort(se, se + sz);
    for(i = 0; i < sz; ++i) {
        double nowl, nowr;
        nowl = se[i].first;
        nowr = se[i].second;
        for(j = i + 1; j < sz; ++j) {
            if(More(se[j].first, nowr)) {
                break;
            }else {
                if(More(se[j].second, nowr)) nowr = se[j].second;
            }
        }
        ret += nowr - nowl;
        i = j - 1;
    }
    return ret;
}
#define fs(x) ((x) < 0 ? (-(x)) : (x))
inline double rsimp(double l, double m, double r, double sl, double sm, double sr, double tot) {
    double m1 = (l + m) * 0.5, m2 = (m + r) * 0.5;
    double s0 = f(m1), s2 = f(m2);
    double gl = (sl + sm + s0 + s0 + s0 + s0) * (m - l), gr = (sm + sr + s2 + s2 + s2 + s2) * (r - m);
    if(fs(gl + gr - tot) < EPS) return gl + gr;
    return rsimp(l, m1, m, sl, s0, sm, gl) + rsimp(m, m2, r, sm, s2, sr, gr);
}


void deal() {
    int i, j = 0, k;
    for(i = 0; i < m; ++i) {
        s[i] = i;
    }
    sort(s, s + m, cmp0);
    for(i = 0; i < m; ++i){
        for(k = 0; k < j; ++k)
                if(LessEqu((nx[k] - x[s[i]]) * (nx[k] - x[s[i]]) + (ny[k] - y[s[i]]) * (ny[k] - y[s[i]])
                    , (nr[k] - r[s[i]]) * (nr[k] - r[s[i]]))) break;
        if(k == j) {
            nx[j] = x[s[i]];
            ny[j] = y[s[i]];
            nr[j] = r[s[i]];
            s[j] = j;
            j++;
        }
    }
    m = j;
    for(i = 0; i < m; ++i) {
        x[i] = nx[i], y[i] = ny[i], r[i] = nr[i];
    }
}


void Round_S_Union() {
    sort(s, s + m, cmp1);
    double lo, hi, ans = 0.0;
    int i, j;
    for(i = 0; i < m; ++i) {
        xl[i] = x[s[i]] - r[s[i]], xr[i] = x[s[i]] + r[s[i]], r[s[i]] *= r[s[i]];
    }
    for(i = 0; i < m; ++i) {
        double ilo, ihi;
        ilo = xl[i];
        ihi = xr[i];
        for(j = i + 1; j < m; ++j) {
            if(More(xl[j], ihi)) break;
            if(More(xr[j], ihi)) ihi = xr[j];
        }
        double lo = ilo;
        double hi = ihi;
        L = i;
        R = j;
        double mid = (lo + hi) * 0.5;
        double sl = f(lo), sm = f(mid), sr = f(hi);
        double tot = sl + sr + sm + sm + sm + sm;
        ans += rsimp(lo, mid, hi, sl, sm, sr, tot);
        i = j - 1;
    }
    printf("%.2f\n", ans / 6.0);
}


int main() {
    int T, tcase = 1;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++) {
            scanf("%d%d%d", &ps[i].x[0], &ps[i].x[1], &ps[i].k);
            ps[i].id = i;
            qs[i] = ps[i];
        }
        Build_kdTree(0, n - 1, qs, 0);
        for(int i = 0; i < n; i++) {
            Query(0, n - 1, qs, ps[i]);
            Point req = q.top();
            ps[i].dis = ps[i].distance(req);
            while(!q.empty()) {
                q.pop();
            }
        }
        sort(ps, ps + n, cmp_dis);
        for(int i = 0; i < m; i++) {
            x[i] = ps[i].x[0];
            y[i] = ps[i].x[1];
            r[i] = sqrt(1.0 * ps[i].dis);
        }
        deal();
        Round_S_Union();
    }
    return 0;
}


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值