• [BZOJ1604] [Usaco2008 Open] Cow Neighborhoods 奶牛的邻居 (queue & set)


    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.

    HINT

    Source

      Gold

    Solution

      设点$(x',y')$表示$(x+y,x-y)$,则:

      有这样一个性质:两个点的曼哈顿距离为$max(|x'_1-x'_2|,|y'_1-y'_2|)$

      所以先将所有点预处理,之后按$x'$坐标排序。

      用一个队列维护$x'$使队列里所有元素$x'$之差不超过$C$,用set维护$y'$

      若新插入元素的前驱或后继与该元素之差小于等于$C$就用并查集把它们连起来

      数一下联通块的个数就行了。

     1 #include <bits/stdc++.h>
     2 #define fir first
     3 #define sec second
     4 #define mp make_pair
     5 using namespace std;
     6 typedef pair<int, int> pii;
     7 const int INF = 2100000000;
     8 set<pii> S;
     9 set<pii>::iterator it;
    10 queue<int> Q;
    11 pii a[100005];
    12 int fa[100005], siz[100005];
    13  
    14 int getfa(int x)
    15 {
    16     return fa[x] = x == fa[x] ? x : getfa(fa[x]);
    17 }
    18  
    19 int main()
    20 {
    21     int n, c, u, v, cnt = 0, mx = 1;
    22     cin >> n >> c;
    23     for(int i = 1; i <= n; i++)
    24     {
    25         cin >> a[i].fir >> a[i].sec;
    26         a[i].fir += a[i].sec;
    27         a[i].sec = a[i].fir - 2 * a[i].sec;
    28         fa[i] = i;
    29     }
    30     sort(a + 1, a + n + 1);
    31     S.insert(mp(-INF, 0)), S.insert(mp(INF, 0));
    32     Q.push(1), S.insert(mp(a[1].sec, 1));
    33     for(int i = 2; i <= n; i++)
    34     {
    35         while(!Q.empty() && a[i].fir - a[Q.front()].fir > c)
    36         {
    37             u = Q.front(), Q.pop();
    38             S.erase(mp(a[u].sec, u));
    39         }
    40         it = S.lower_bound(mp(a[i].sec, 0));
    41         if(it->sec && it->fir - a[i].sec <= c)
    42         {
    43             u = getfa(it->sec), v = getfa(i);
    44             if(u != v) fa[u] = v;
    45         }
    46         if((--it)->sec && a[i].sec - it->fir <= c)
    47         {
    48             u = getfa(it->sec), v = getfa(i);
    49             if(u != v) fa[u] = v;
    50         }
    51         Q.push(i), S.insert(mp(a[i].sec, i));
    52     }
    53     for(int i = 1; i <= n; i++)
    54     {
    55         if(++siz[getfa(i)] == 1) cnt++;
    56         mx = max(mx, siz[getfa(i)]);
    57     }
    58     cout << cnt << ' ' << mx << endl;
    59     return 0;
    60 }
    View Code
  • 相关阅读:
    java内存回收机制
    scala学习
    [java实现]找一个数组的最大和的连续子数组(时间复杂度 O(n))
    linux 进程的创建
    linux中的进程和线程
    linux 文件系统
    gdb 调试程序
    makefile
    linux下的gcc编译器
    socket 网络编程
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5525433.html
Copyright © 2020-2023  润新知