第1行输入N和C,之后N行每行输入一只奶牛的坐标.
仅一行,先输出牛群数,再输出最大牛群里的牛数,用空格隔开.
由于本人智商问题这玩意儿困扰了我好久。。。
看了网上大牛的解释对于曼哈顿距离做如下处理:
设任意两点坐标分别为(x1,y1)与(x2,y2)
两点曼哈顿距离有四种情况:
x1 - x2 + y1 - y2
x1 - x2 + y2 - y1
x2 - x1 + y1 - y2
x2 - x1 + y2 - y1
设X = x + y,Y = x - y
于是上述四个式子简化为max(|X1 - X2|,|Y1 - Y2|)
然后维护X的同时将每个Y写入treap就好啦。。
(每个点看看在treap的前驱后继能不能连边就是咯)
//对于我的代码。。没事开long long就WA,生气用int结果AC了。。真是呵呵哒
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<map>
#include<cmath>
#include<set>
using namespace std;
const int maxn = 5e5 + 10;
const int INF = 2e9 + 10;
typedef int LL;
struct P{
LL x,y;
bool operator < (const P &b) const{
return x + y < b.x + b.y;
}
}poi[maxn];
LL n,i,j,father[maxn],c,Size = 0,Max = 0,Siz[maxn];
queue <LL> q;
LL fa (LL k)
{
return k == father[k]?k:father[k] = fa(father[k]);
}
class data{
private :
struct Node{
Node *ch[2];
LL key,pri,N;
}pool[maxn],*root,*tot;
LL pos (Node *a,LL N)
{
LL N_key = poi[N].x - poi[N].y;
if (a -> key > N_key) return 0;
if (a -> key < N_key) return 1;
if (a -> N < N) return 1;
if (a -> N > N) return 0;
return -1;
}
void rotate (Node *&x,LL d)
{
Node *y = x -> ch[d];
x -> ch[d] = y -> ch[d^1];
y -> ch[d^1] = x;
x = y;
}
void Insert (Node *&x,LL N,LL pri)
{
LL key = poi[N].x - poi[N].y;
if (x == NULL)
{
x = tot++;
x -> key = key;
x -> N = N;
x -> pri = pri;
return;
}
LL d = pos(x,N);
Insert(x -> ch[d],N,pri);
if (x -> ch[d] -> pri > x -> pri) rotate(x,d);
}
void Remove(Node *&x,LL N)
{
LL d = pos(x,N);
if (d == -1)
{
if (x -> ch[0] != NULL && x -> ch[1] != NULL)
{
LL d2 = x -> ch[0] -> pri > x -> ch[1] -> pri?0:1;
rotate(x,d2);
Remove(x -> ch[d2^1],N);
}
else {
if (x -> ch[0] == NULL && x -> ch[1] == NULL)
{
x = NULL;
return;
}
if (x -> ch[0] == NULL) x = x -> ch[1];
else x = x -> ch[0];
}
}
else Remove(x -> ch[d],N);
}
LL find_pre(LL N)
{
Node *x = root;
LL N_key = poi[N].x - poi[N].y;
LL Max = -INF - 10,ret;
while (x != NULL)
{
if (x -> key == N_key) return x -> N;
LL d = pos(x,N);
if (x -> key < N_key && x -> key > Max) Max = x -> key,ret = x -> N;
x = x -> ch[d];
}
return ret;
}
LL find_next(LL N)
{
Node *x = root;
LL N_key = poi[N].x - poi[N].y;
LL Min = INF + 10,ret;
while (x != NULL)
{
LL d = pos(x,N);
if (x -> key == N_key) return x -> N;
if (x -> key > N_key && x -> key < Min) Min = x -> key,ret = x -> N;
x = x -> ch[d];
}
return ret;
}
public :
data () {
root = NULL;
tot = pool;
}
void Ins (LL N) {
Insert (root,N,rand());
}
void Rem (LL N) {
Remove (root,N);
}
LL F_P (LL N) {
return find_pre(N);
}
LL F_N (LL N) {
return find_next(N);
}
};
int main()
{
#ifndef ONLINE_JUDGE
#ifndef YZY
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#else
freopen("yzy.txt","r",stdin);
#endif
#endif
static data tree;
cin >> n >> c;
for (i = 1; i <= n; i++)
{
scanf("%d%d",&poi[i].x,&poi[i].y);
father[i] = i;
Siz[i] = 1;
}
father[n + 1] = n + 1;
father[0] = 0;
poi[n + 1].x = INF;
poi[n + 1].y = 0;
poi[0].x = -INF;
poi[0].y = 0;
tree.Ins(0);
tree.Ins(n + 1);
sort (poi + 1,poi + n + 1);
for (i = 1; i <= n; i++)
{
while (!q.empty())
{
LL I_key = poi[i].x + poi[i].y;
LL k = q.front();
LL k_key = poi[k].x + poi[k].y;
if (I_key - k_key > c) tree.Rem(k),--Size,q.pop();
else break;
}
if (Size >= 1)
{
LL Pre = tree.F_P(i);
LL Next = tree.F_N(i);
LL f_p = fa(Pre),p_key = poi[Pre].x - poi[Pre].y;
LL f_i = fa(i),i_key = poi[i].x - poi[i].y;
if (f_p != f_i && abs(p_key - i_key) <= c && Pre != 0)
{
father[f_p] = f_i;
Siz[f_i] += Siz[f_p];
}
LL f_n = fa(Next),n_key = poi[Next].x - poi[Next].y;
if (f_n != f_i && Next != n + 1 && abs(n_key - i_key) <= c)
{
father[f_n] = f_i;
Siz[f_i] += Siz[f_n];
}
}
tree.Ins(i);
++Size;
q.push(i);
}
LL ans = 0;
for (i = 1; i <= n; i++)
if (father[i] == i)
{
++ans;
Max = max(Siz[i],Max);
}
printf("%d %d",ans,Max);
return 0;
}