Sicily 1912. Crop circles

1912. Crop circles

Constraints

Time Limit: 3 secs, Memory Limit: 64 MB

Description

Is there really a monster living in Loch Ness?
Did the lost city of Atlantis ever exist?
Are UFOs tricks of the light, or actually vehicles from outer space?
Who is responsible for the strange patterns called crop circles-clever hoaxers or alien beings?
As we can see, there are so many mysterious places, creatures and events in the world which puzzled people for centuries. In this problem, we won't go through all that puzzles. Which we are interested in is this one - crop circles.

You have probably seen pictures of crop circles. (i.e. see above) They are circular patterns which mysteriously appear in fields of crop, such as wheat and barley. For research, we model these patterns as N circles in the plane and number them with 1, 2,..., N . Each of them has its center (Xi, Yi) , radius Ri and an importance value Vi which is evaluated by the scientists.

After our observation, we found that there aren't any two circles touch each other in the crop circles. But it's possible that a circle is completely within another one. When we are in a certain circle, we should pass through its borderline once in order to get out from it.

For two distinct circles A and B, if one can go to B from A without passing through more than K borderlines, we say that A and B are connected. Here comes the problem: For all connected cycle pairs (A, B), what's the maximum difference of the importance value between them? The difference of the importance value between A and B can be defined as | VA - VB| .


For example, look at the picture below. For K = 3 , the optimal solution is to select the circle 1 and 3 which make the difference of importance value 220. And there are 3 borderlines between circle 1 and 3.

| V5 - V1| = 300 , which is larger than 220, but circle 5 and circle 1 are not connected. There're 4 borderlines between them, so we won't consider these kinds of pairs.

Input

 The first line of input gives the number of cases T<=20 . T test cases follow.

The first line of each case contains two integers N , K as described above. (1 < N < 50001, 1 < K < 101) .

Next follow N lines, each contains four integers Xi , Yi , Ri , Vi , separated by spaces. The i -th line specifying the information of the i -th circle, where (Xi, Yi) are the coordinates of the center, Ri specifies the radius and Vi is the importance value. (0 < Ri ≤ 2 * 10^8, -10^9 < Xi, Yi, Vi < 10^9)

Output

 For each test case you should output a single line containing ``Case X : Y " (quotes for clarity) where X is the number of the test case (starting at 1) and Y is the maximum difference of importance value between two connected circles.

Sample Input

2 
5 3 
10 10 1 -200 
0 0 8 10 
-2 2 2 20 
3 -3 3 2 
3 -3 1 100 
3 2 
-200 0 1 0 
0 0 100 2 
200 0 1 10

Sample Output

Case 1: 220 

Case 2: 10

// Problem#: 1912
// Submission#: 3591077
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <set>
using namespace std;

const int MAXN = 50005;
const int INF = 0x7fffffff;
const double EPS = 1e-9;

int n, k;
int x[MAXN], y[MAXN], r[MAXN], v[MAXN];
int fa[MAXN];
int cur[MAXN];
int Prev[MAXN];

inline long long sqr(long long x) {return x * x;}

struct Event {
    int id, type;
    Event(int id = 0, int type = 0) {
        this->id = id;
        this->type = type;
    }
    long long x_pos() const {
        return x[id] + r[id] * type;
    }
    bool operator < (const Event & t) const {
        long long dt = (long long)x_pos() - t.x_pos();
        if (dt != 0) return dt < 0;
        return id < t.id;
    }
}e[MAXN * 2];

int x_cut;

struct Intersection {
    int id, type;
    Intersection(int id = 0, int type = 0) {
        this->id = id;
        this->type = type;
    }
    double y_pos() const {
        long long s = sqr(r[id]) - sqr(x_cut - x[id]);
        if (s < 0) s = 0;
        return y[id] + sqrt((double)s) * type;
    }
    bool operator < (const Intersection & t) const {
        double dt = y_pos() - t.y_pos();
        if (fabs(dt) > EPS) return dt < 0;
        if (id != t.id) return id < t.id;
        return type < t.type;
    }
};

set<Intersection> bst;

void build() {
    for (int i = 0; i < n; i++) {
        e[i] = Event(i, - 1);
        e[i + n] = Event(i, 1);
    }
    sort(e, e + n * 2);
    bst.clear();
    for (int i = 0; i < n * 2; i++) {
        x_cut = e[i].x_pos();
        int cur = e[i].id;
        if (e[i].type < 0) {
            bst.insert(Intersection(cur, 1));
            set<Intersection>::iterator it;
            it = bst.insert(Intersection(cur, -1)).first;
            if (it == bst.begin()) {
                fa[cur] = n;
            } else {
                it--;
                if (it->type == -1) {
                    fa[cur] = it->id;
                } else {
                    fa[cur] = fa[it->id];
                }
            }
        } else {
            bst.erase(Intersection(cur, 1));
            bst.erase(Intersection(cur, -1));
        }
    }
}

int main() {
    int cs;
    scanf("%d", &cs);
    for (int cid = 1; cid <= cs; cid++) {
        scanf("%d%d", &n, &k);
        for (int i = 0; i < n; i++) scanf("%d%d%d%d", x + i, y + i, r + i, v + i);
        build();
        v[n] = INF;
        memcpy(cur, v, sizeof(int) * (n + 1));
        for (int i = 1; i <= k; i++) {
            memcpy(Prev, cur, sizeof(int) * (n + 1));
            for (int a = 0; a < n; a++) {
                int b = fa[a];
                cur[a] = min(cur[a], Prev[b]);
                cur[b] = min(cur[b], Prev[a]);
            }
        }
        int ret = 0;
        for (int a = 0; a < n; a++) ret = max(ret, v[a] - cur[a]);
        printf("Case %d: %d\n", cid, ret);
    }
    return 0;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值