• [BZOJ1604][Usaco2008 Open]Cow Neighborhoods 奶牛的邻居


    [BZOJ1604][Usaco2008 Open]Cow Neighborhoods 奶牛的邻居

    试题描述

    了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的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均同属一个群.
        给出奶牛们的位置,请计算草原上有多少个牛群,以及最大的牛群里有多少奶牛

    输入

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

    输出

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

    输入示例

    4 2
    1 1
    3 3
    2 2
    10 10

    输出示例

    2 3

    数据规模及约定

    见“试题描述

    题解

    把曼哈顿距离转换成“切比雪夫”距离,即每个点 (x, y) 变成 (x+y, x-y),那么两点 (x1, y1) (x2, y2) 间曼哈顿距离 = max{ |x1 - x2|, |y1 - y2| },于是把新点按 x 排序,滑动窗口控制成 c 的宽度,然后平衡树维护 y 这一维,每次找到一个点的前驱、后继如果 y 坐标相差小于等于 c 就在并查集中合并一下。最后随便统计统计。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
     
    int read() {
        int x = 0, f = 1; char c = getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
     
    #define maxn 100010
    #define oo 2147483647
    struct Node {
        int v, r, id;
        Node() {}
        Node(int _1, int _2, int _3): v(_1), r(_2), id(_3) {}
        bool operator < (const Node& t) const { return v != t.v ? v < t.v : id < t.id; }
        bool operator == (const Node& t) const { return v == t.v && id == t.id; }
    } ns[maxn];
    int rt, ToT, ch[2][maxn], fa[maxn];
    void rotate(int u) {
        int y = fa[u], z = fa[y], l = 0, r = 1;
        if(z) ch[ch[1][z]==y][z] = u;
        if(ch[1][y] == u) swap(l, r);
        fa[u] = z; fa[y] = u; fa[ch[r][u]] = y;
        ch[l][y] = ch[r][u]; ch[r][u] = y;
        return ;
    }
    void insert(int& o, int v, int id) {
        if(!o) {
            ns[o = ++ToT] = Node(v, rand(), id);
            return ;
        }
        bool d = ns[o] < Node(v, -1, id);
        insert(ch[d][o], v, id); fa[ch[d][o]] = o;
        if(ns[ch[d][o]].r > ns[o].r) {
            int t = ch[d][o];
            rotate(t); o = t;
        }
        return ;
    }
    void del(int& o, int v, int id) {
        if(!o) return ;
        if(ns[o] == Node(v, -1, id)) {
            if(!ch[0][o] && !ch[1][o]) o = 0;
            else if(!ch[0][o]) {
                int t = ch[1][o]; fa[t] = fa[o]; o = t;
            }
            else if(!ch[1][o]) {
                int t = ch[0][o]; fa[t] = fa[o]; o = t;
            }
            else {
                bool d = ns[ch[1][o]].r > ns[ch[0][o]].r;
                int t = ch[d][o]; rotate(t); o = t;
                del(ch[d^1][o], v, id);
            }
        }
        else {
            bool d = ns[o] < Node(v, -1, id);
            del(ch[d][o], v, id);
        }
        return ;
    }
    Node Findlow(int o, int v, int id) {
        Node err(-oo, 233, -1), que(v, -1, id);
        if(!o) return err;
        bool d = ns[o] < que;
        return max(ns[o] < que ? ns[o] : err, Findlow(ch[d][o], v, id));
    }
    Node Findupp(int o, int v, int id) {
        Node err(oo, 233, -1), que(v, -1, id);
        if(!o) return err;
        bool d = ns[o] < que;
        return min(que < ns[o] ? ns[o] : err, Findupp(ch[d][o], v, id));
    }
     
    struct Point {
        int x, y;
        Point() {}
        Point(int _, int __): x(_), y(__) {}
        bool operator < (const Point& t) const { return x != t.x ? x < t.x : y < t.y; }
    } ps[maxn];
     
    int pa[maxn], siz[maxn];
    int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[x]); }
     
    int main() {
        int n = read(), c = read();
        for(int i = 1; i <= n; i++) {
            int x = read(), y = read();
            ps[i] = Point(x + y, x - y);
        }
         
        sort(ps + 1, ps + n + 1);
        int cnt = n, mxs = 1;
        for(int i = 1; i <= n; i++) pa[i] = i, siz[i] = 1;
        int l = 1, r = 1;
        for(; r <= n; r++) {
            while(l <= r && ps[r].x - ps[l].x > c) del(rt, ps[l].y, l), l++;
            Node tmp = Findlow(rt, ps[r].y, r);
    //      printf("tmp: %d %d
    ", tmp.id, tmp.v);
            if(tmp.v != -oo && ps[r].y - tmp.v <= c) {
                int u = findset(r), v = findset(tmp.id);
                if(u != v) siz[u] += siz[v], mxs = max(mxs, siz[u]), pa[v] = u, cnt--;
            }
            tmp = Findupp(rt, ps[r].y, r);
    //      printf("tmp: %d %d
    ", tmp.id, tmp.v);
            if(tmp.v != oo && tmp.v - ps[r].y <= c) {
                int u = findset(r), v = findset(tmp.id);
                if(u != v) siz[u] += siz[v], mxs = max(mxs, siz[u]), pa[v] = u, cnt--;
            }
            insert(rt, ps[r].y, r);
        }
         
        printf("%d %d
    ", cnt, mxs);
         
        return 0;
    }
    
  • 相关阅读:
    RHEL5.8使用yum安装xclock
    Linux下磁盘分区、挂载、卸载操作记录
    CentOS6.5磁盘分区和挂载操作记录
    CentOS环境下下调整home和根分区大小
    PowerDesigner连接Oracle数据库(32位)反向生成物理数据模型
    Create-React-App脚手架使用方法
    react 简书开发笔记
    本地连接服务器的mongodb
    使用mongoose连接mongodb(转载文章)
    将koa+vue部署到服务器
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6187234.html
Copyright © 2020-2023  润新知