[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;
}

 

转载于:https://www.cnblogs.com/ruoruoruo/p/7545124.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
旅游社交小程序功能有管理员和用户。管理员有个人中心,用户管理,每日签到管理,景点推荐管理,景点分类管理,防疫查询管理,美食推荐管理,酒店推荐管理,周边推荐管理,分享圈管理,我的收藏管理,系统管理。用户可以在微信小程序上注册登录,进行每日签到,防疫查询,可以在分享圈里面进行分享自己想要分享的内容,查看和收藏景点以及美食的推荐等操作。因而具有一定的实用性。 本站后台采用Java的SSM框架进行后台管理开发,可以在浏览器上登录进行后台数据方面的管理,MySQL作为本地数据库,微信小程序用到了微信开发者工具,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得旅游社交小程序管理工作系统化、规范化。 管理员可以管理用户信息,可以对用户信息添加修改删除。管理员可以对景点推荐信息进行添加修改删除操作。管理员可以对分享圈信息进行添加,修改,删除操作。管理员可以对美食推荐信息进行添加,修改,删除操作。管理员可以对酒店推荐信息进行添加,修改,删除操作。管理员可以对周边推荐信息进行添加,修改,删除操作。 小程序用户是需要注册才可以进行登录的,登录后在首页可以查看相关信息,并且下面导航可以点击到其他功能模块。在小程序里点击我的,会出现关于我的界面,在这里可以修改个人信息,以及可以点击其他功能模块。用户想要把一些信息分享到分享圈的时候,可以点击新增,然后输入自己想要分享的信息就可以进行分享圈的操作。用户可以在景点推荐里面进行收藏和评论等操作。用户可以在美食推荐模块搜索和查看美食推荐的相关信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值