bzoj1604 [Usaco2008 Open]Cow Neighborhoods Cow's Neighborhoods Neighbors (Manhattan Distance Turn Chebyshev Distance+and Search+set)

Keywords: PHP less

bzoj1604 [Usaco2008 Open]Cow Neighborhoods Neighbors

The title of authority should be affixed below.

Origin address: http://www.lydsy.com/JudgeOnline/problem.php?id=1604

Title:
Everyone who knows about cows knows that cows like to flock together. Looking at John's N(1 < N < 100000) cows, you will find that they have formed several "herds". Each cow has a unique coordinate Xi, Yi(l < Xi, Yi < 1.10 ^ 9); Xi, Yi < integer. When one of the following two conditions is met, two cows i and j belong to the same group. Group:
1. The Manhattan distance of two dairy cows does not exceed C(1 < C < 10 ^ 9), that is lXi - xil+IYi - Yil < C.
2. Two cows have common neighbors. That is, there is a cow k, so that i and k, j and K belong to the same group.
Given the location of the cows, please calculate how many herds there are on the grassland and how many cows there are in the largest herd.
Input

Line 1 enters N and C, and then line N enters the coordinates of a cow.

Output

Only one line, output the number of cattle first, then output the number of cattle in the largest cattle herd, separated by spaces.

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.

Data range
1 < N < 100000, Xi, Yi(l < Xi, Yi < 1.10 ^ 9), Xi, Yi < integers
1≤C≤10^9

Explanation:
For the given form of Manhattan distance: | Xi - xi|+|Yi - yi | < C.
The sum of absolute values, which is very difficult to deal with, here is a quite classical way of transformation:
Manhattan Distance Chebyshev Distance
For two points (x1,y1), (x2,y2), their Manhattan distance | X1 - x2 |+ | Y1 - Y2 | <=c
Namely
 -c<=x1 - x2+y1-y2<=c   (1)
 -c<=x1 - x2-y1+y2<=c   (2)
It can be translated into:
 -c<=(x1+y1)-(x2+y2)<=c   (1)
 -c<=(x1- y1)-(x2- y2)<=c   (2)
Let's make X=x+y, Y=x-y.
The original transformation into:
 |X1-X2|≤C  (1)
 |Y1-Y2|≤C   (2)
This translates into a more manageable Chebyshev distance.
When we input, we process it. We store x+y as X coordinate and x-y as Y coordinate.
Therefore, two points are directly connected if and only if the difference between their X coordinates is <= C and the difference between their Y coordinates is <= c, while the indirect connection is obviously through direct connection, so we consider adding directly connected points and collecting them.

An algorithm is given here:
Sort all points by x coordinates, maintain a queue of x coordinate difference <= C in one direction from each point in turn, add a point to the set sorted by Y coordinates, find its front and rear drivers in the set, and if the difference between front and back drivers and his y <= c, add him and his front/back drivers to the set and search them.

Here is a superficial proof:
For example, i point coordinates (x, y) (after transformation), some points whose x coordinates are less than X are directly connected with i. We only need to add and collect the first points whose y coordinates are less than or greater than his. Because of the difference between these points and his x coordinates, the difference between the Y coordinates is <= C. They are all directly connected, so that only the nearest two points of the difference between the Y coordinates are connected to each point, just like a chain. It is guaranteed that all these points are joined and collected.

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<set>
using namespace std;
const int N=100005;
int n,c,fa[N],size[N];
const int inf=1e9+10;
struct node
{
    int x,y;
    node(){}
    node(int x,int y):x(x),y(y){}
    bool friend operator<(const node &A,const node &B)
    {
        return A.y<B.y;
    }
    bool friend operator==(const node &A,const node &B)
    {
        return (A.x==B.x)&&(A.y==B.y);
    }
}p[N];
bool cmp(const node &A,const node &B)
{
    return A.x<B.x;
}
int getfa(int x)
{
    if(fa[x]==x) return x;
    else return fa[x]=getfa(fa[x]);
}
bool cmpy(int &A,int &B)
{
    return p[A].y<p[B].y;
}
void merge(int x,int y)
{
    int fx=getfa(x); int fy=getfa(y);
    if(fx==fy) return;  
    fa[fy]=fx;
}
set<pair<int,int> > S;

int main()
{
    scanf("%d%d",&n,&c);
    for(int i=1;i<=n;i++) fa[i]=i; 
    for(int i=1;i<=n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        p[i].x=x+y; p[i].y=x-y;
    }
    sort(p+1,p+n+1,cmp);
    S.insert(make_pair(-inf,-inf)); S.insert(make_pair(inf,inf));
    int lf=1;
    S.insert(make_pair(p[1].y,1));
    for(int i=2;i<=n;i++)
    {
        while(p[i].x-p[lf].x>c)
        {S.erase(make_pair(p[lf].y,lf));lf++;}
        S.insert(make_pair(p[i].y,i));
        pair<int,int> pre=*--S.find(make_pair(p[i].y,i));
        pair<int,int> nxt=*++S.find(make_pair(p[i].y,i));
        if(pre.second!=-inf&&p[i].y-pre.first<=c) merge(i,pre.second);
        if(nxt.second!=inf&&nxt.first-p[i].y<=c) merge(i,nxt.second);       
    }
    int cnt=0; int mx=-1;
    for(int i=1;i<=n;i++)
    {
        int fx=getfa(i);
        size[fx]++; if(fx==i) cnt++;
    }
    for(int i=1;i<=n;i++) mx=max(mx,size[i]);
    printf("%d %d\n",cnt,mx);
    return 0;
}

I started by following it, because I ignored the possibility that j might eventually appear.

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<set>
using namespace std;
const int N=100005;
int n,c,fa[N],size[N];
const int inf=1e9+10;
struct node
{
    int x,y;
    node(){}
    node(int x,int y):x(x),y(y){}
    bool friend operator<(const node &A,const node &B)
    {
        return A.y<B.y;
    }
    bool friend operator==(const node &A,const node &B)
    {
        return (A.x==B.x)&&(A.y==B.y);
    }
}p[N];
bool cmp(const node &A,const node &B)
{
    return A.x<B.x;
}
int getfa(int x)
{
    if(fa[x]==x) return x;
    else return fa[x]=getfa(fa[x]);
}
bool cmpy(int &A,int &B)
{
    return p[A].y<p[B].y;
}
void merge(int x,int y)
{
    int fx=getfa(x); int fy=getfa(y);
    if(fx==fy) return;  
    fa[fy]=fx;
}
set<pair<int,int> > S;

int main()
{
    scanf("%d%d",&n,&c);
    for(int i=1;i<=n;i++) fa[i]=i; 
    for(int i=1;i<=n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        p[i].x=x+y; p[i].y=x-y;
    }
    sort(p+1,p+n+1,cmp);
    S.insert(make_pair(-inf,-inf)); S.insert(make_pair(inf,inf));
    int i=1,j=1;
    for(i=1;i<=n;i++)
    {
        S.insert(make_pair(p[i].y,i));
        while((j<n&&p[j+1].x-p[i].x<=c))
        {
            j++;
            S.insert(make_pair(p[j].y,j));
            pair<int,int> pre=*--S.find(make_pair(p[j].y,j));
            pair<int,int> nxt=*++S.find(make_pair(p[j].y,j));
            if(pre.second!=-inf&&p[j].y-pre.first<=c) merge(j,pre.second);
            if(nxt.second!=inf&&nxt.first-p[j].y<=c) merge(j,nxt.second);
        }
        S.erase(make_pair(p[i].y,i));
    }

    int cnt=0; int mx=-1;
    for(int i=1;i<=n;i++)
    {
        int fx=getfa(i);
        size[fx]++; if(fx==i) cnt++;
    }
    for(int i=1;i<=n;i++) mx=max(mx,size[i]);
    printf("%d %d\n",cnt,mx);
    return 0;
}

Posted by foreverhex on Thu, 13 Dec 2018 19:51:17 -0800