1. 程式人生 > >bzoj 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的鄰居——排序+貪心+set

bzoj 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的鄰居——排序+貪心+set

hid lar 存在 max printf data 後繼 pty 我們

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.
————————————————————————————— 這道題首先我們進行一個轉化 就是 將每個點變成(sx=(x+y), sy=( x-y)) 這樣兩點的曼哈頓距離就是 max( |sx1 – sx2|, |sy1 – sy2|)=max( x1-x2+y1-y2 , x1-x2-y1+y2 ) 這個可以分類證明 分四類 1 x1>x2 &&y1>y2 那麽 sx1-sx2 就是曼哈頓距離的正常表示方法 且sx1-sx2>sy1-sy2
2 x1<x2&&y1<y2 因為是絕對值 所以其實形式是一樣的 (同上) 3 x1>x2&&y1<y2 那麽 |x1-x2|+|y1-y2| = x1-x2+y2-y1 就是 sy1-sy2 也易得 sy1-sy2>sx1-sx2 3 x1>x2&&y2>y1 一樣是絕對值 倒一下就好了(同上) 這樣之後我們把點按 sx 排序 維護一個隊列 對頭的坐標和當前點的坐標的sx的差 不能超過 c 因為超過 c 他必然不可能和當前點曼哈頓距離小於c 所以如果超過我們要刪除(順便在平衡樹把這個點刪了) 然後我們維護一個sy的平衡樹 求一下當前點sy在平衡樹裏面的前驅後繼 看一下能不能合並 如果可以就合並在一個並查集 最後掃一波就可以得到答案了 至於為什麽可以這麽合並 因為就算別的點在前驅的下面或者後繼的下面並且他們可以和當前點合並 那麽他們一定在之前和前驅後繼或者是再前再後合並 所以這樣的貪心是可行的 技術分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
using namespace std;
const int M=150007;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int n,c;
int f[M],h[M],ans,mx;
int find(int x){while(f[x]!=x) x=f[x]=f[f[x]]; return x;}
struct node{
    int x,y,id;
    bool operator <(const node& k)const{return x<k.x;}
}e[M];
struct pos{
    int y,id;
    bool operator <(const pos& k)const{return y!=k.y?y<k.y:id<k.id;}
};
std::queue<int>q;
std::multiset<pos>tr;
std::multiset<pos>::iterator it;
int main(){
    int x,y;
    n=read(); c=read();
    for(int i=1;i<=n;i++){
        x=read(); y=read();
        f[i]=i; e[i].x=x+y,e[i].y=x-y; e[i].id=i;
    }
    sort(e+1,e+1+n);
    for(int i=1;i<=n;i++){
        while(!q.empty()&&e[i].x-e[q.front()].x>c){
            int now=q.front(); q.pop();
            tr.erase(tr.find((pos){e[now].y,e[now].id}));
        }
        q.push(i);
        it=tr.insert((pos){e[i].y,e[i].id});
        if(it!=tr.begin()){
            --it;
            if(e[i].y-(it->y)<=c){
                int p=find(e[i].id),q=find(it->id);
                f[q]=p;
            }
            ++it;
        }
        ++it;
        if(it!=tr.end()){
            if(it->y-e[i].y<=c){
                int p=find(e[i].id),q=find(it->id);
                f[q]=p;
            }
        }
    }
    for(int i=1;i<=n;i++){
        int x=find(e[i].id);
        if(!h[x]) ans++;
        h[x]++; mx=max(mx,h[x]);
    }printf("%d %d\n",ans,mx);
    return 0;
}
View Code

bzoj 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的鄰居——排序+貪心+set