zoukankan      html  css  js  c++  java
  • [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' ight|,left|y_i'-y_j' ight|)$
    处理完之后先按照$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
    ", ans, tot);
        return 0;
    }
  • 相关阅读:
    ACM学习历程—HDU1719 Friend(数论)
    封装的方法
    MySql-rules
    MySql
    java深入探究07-jsp
    java深入探究06
    Jquery
    Ajax
    java深入探究05
    Oracle——索引,序列,触发器
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/7545124.html
Copyright © 2011-2022 走看看