[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

 

posted @ 2016-05-24 23:34  CtrlCV  阅读(287)  评论(0编辑  收藏  举报