[Usaco2008 Open]Cow Neighborhoods 奶牛的邻居

1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居

Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1102  Solved: 446 [Submit][Status][Discuss]

Description

了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l≤Xi,Yi≤[1..10^9];Xi,Yi∈整数.当满足下列两个条件之一,两只奶牛i和j是属于同一个群的:
  1.两只奶牛的曼哈顿距离不超过C(1≤C≤10^9),即lXi - xil+IYi - Yil≤C.
  2.两只奶牛有共同的邻居.即,存在一只奶牛k,使i与k,j与k均同属一个群.
    给出奶牛们的位置,请计算草原上有多少个牛群,以及最大的牛群里有多少奶牛

Input

   第1行输入N和C,之后N行每行输入一只奶牛的坐标.

Output

仅一行,先输出牛群数,再输出最大牛群里的牛数,用空格隔开.

Sample Input

4 2 1 1 3 3 2 2 10 10
* Line 1: A single line with a two space-separated integers: the         number of cow neighborhoods and the size of the largest cow         neighborhood.

Sample Output

2 3
OUTPUT DETAILS: There are 2 neighborhoods, one formed by the first three cows and the other being the last cow. The largest neighborhood therefore has size 3.
先处理曼哈顿距离
把每个点从$(x, y)$变为$(x',y')$,其中$x'=x+y,y'=x-y$,这样两个点$(i,j)$的曼哈顿距离就变为了$max(\left|x_i'-x_j'\right|,\left|y_i'-y_j'\right|)$
处理完之后先按照$x'$排序,再维护一个队列,里面$x'$的大小之差不超过$c$
然后对里面维护以$y'$为关键字的平衡树,查找前驱后继,如果$y'$的差不超过$c$,则用并查集加到同一个集合

 

#include <set>
#include <cstdio>
#include <algorithm>
using namespace std; 
char buf[10000000], *ptr = buf - 1;
inline int readint(){
    int n = 0;
    char ch = *++ptr;
    while(ch < '0' || ch > '9') ch = *++ptr;
    while(ch <= '9' && ch >= '0'){
        n = (n << 1) + (n << 3) + ch - '0';
        ch = *++ptr;
    }
    return n;
}
const int maxn = 100000 + 10;
int N, c, ans;
struct Node{
    int x, y, id;
    Node(){}
    Node(int _x, int _y, int _id): x(_x), y(_y), id(_id){}
}a[maxn];
class cmp1{
    public:
        bool operator () (const Node &a, const Node &b){
            return a.x < b.x;
        }
};
class cmp2{
    public:
        bool operator () (const Node &a, const Node &b){
            if(a.y != b.y) return a.y < b.y;
            else return a.x < b.x;
        }
};
set<Node, cmp2> s;
int fa[maxn], cnt[maxn] = {0};
int Find(int x){
    return x == fa[x] ? x : fa[x] = Find(fa[x]);
}
inline void Union(int x, int y){
    x = Find(x);
    y = Find(y);
    if(x != y){
        fa[x] = y;
        ans --;
    }
}
void solve(){
    int now = 1;
    s.insert(a[1]);
    set<Node>::iterator it1, it2;
    for(int i = 2; i <= N; i++){
        while(a[i].x - a[now].x > c){
            s.erase(s.find(a[now]));
            now++;
        }
        s.insert(a[i]);
        it1 = it2 = s.find(a[i]);
        if(it1 != s.begin()){
            it1--;
            if(a[i].y - (*it1).y <= c) Union(a[i].id, (*it1).id);
        }
        it2++;
        if(it2 != s.end()){
            if((*it2).y - a[i].y <= c) Union(a[i].id, (*it2).id);
        }
    }
}
int main(){
    fread(buf, sizeof(char), sizeof(buf), stdin);
    ans = N = readint();
    c = readint();
    for(int x, y, i = 1; i <= N; i++){
        x = readint();
        y = readint();
        a[i] = Node(x + y, x - y, i);
    }
    sort(a + 1, a + N + 1, cmp1());
    for(int i = 1; i <= N; i++) fa[i] = i;
    solve();
    int tot = 0;
    for(int i = 1; i <= N; i++){
        cnt[Find(i)]++;
        if(cnt[Find(i)] > tot) tot = cnt[Find(i)];
    }
    printf("%d %d\n", ans, tot);
    return 0;
}

 

posted @ 2017-09-18 21:02  Elder_Giang  阅读(314)  评论(0编辑  收藏  举报