题目

【题目描述】

现在有一个无向图 $G = (V, E)$,其中 $V = \{ 1,2,\cdots,n\} $。对于 $V$ 中的任意一个点 $v$,有两个相关的点权 $f_x(v),f_y(v)$。

$(i,j) \in E $ 当且仅当 $ |f_x(i)-f_x(j)| +|f_y(i)-f_y(j)| \le d $。

求 $G$ 的最大团的点数。

【输入格式】

输入第一行读入两个整数 $n,d$,分别表示 $|V|$ 和连边的距离限制。

接下来 $n$ 行,第 $i$ 行两个整数 $f_x(v),f_y(v)$,表示点权。

【输出格式】

输出一个数表示最大团的大小。

【样例输入】

4 1
1 1
2 1
1 1
2 2

【样例输出】

3

【数据范围与提示】

| 测试点 | $n$ | $x,y,d$ |
| ------ | -------------------- | ---------------------- |
| 1,2 | $1 \le n \le 10$ | $1 \le x,y,d \le 10$ |
| 3,4 | $1 \le n \le 500$ | $1 \le x,y,d \le 10^3$ |
| 5,6 | $1 \le n \le 3,000$ | $1 \le x,y,d \le 10^8$ |
| 7,8 | $1 \le n \le 10^5$ | $1 \le x,y,d \le 10^8$ |
| 9,10 | $1 \le n \le 3\times 10^5$ | $1 \le x,y,d \le 10^8$ |

题解

首先由 $ |f_x(i)-f_x(j)| +|f_y(i)-f_y(j)| \le d $ 可以发现求的是平面上两点的曼哈顿距离,然后就变成边长为 $ d $ 菱形的平面覆盖

但是菱形不是很好操作,然后尝试将坐标系旋转 $ 45°$,于是坐标就变成了 $ (x-y,x+y) $,即切比雪夫距离

根据定义,切比雪夫距离为 $max(|x1−x2|,|y1−y2|)$,就很好覆盖了

对于矩形覆盖,可以考虑用线段树动态解决,动态维护保证一维(例如 $x$ 轴) $\leq d$,然后直接查询另一维即可

代码

 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 #define _(d) while(d(isdigit(ch=getchar())))
 4 using namespace std;
 5 int R(){
 6     int x;bool f=1;char ch;_(!)if(ch=='-')f=0;x=ch^48;
 7     _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;}
 8 const int N=3e5+6;
 9 int n,m,d,Y[N],ans,tr[N<<2],tg[N<<2];
10 struct node{int x,y;}s[N];
11 bool cmp(node a,node b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
12 #define LB(x) lower_bound(Y+1,Y+1+m,s[x].y-d)-Y
13 #define UB(x) upper_bound(Y+1,Y+1+m,s[x].y)-Y-1
14 #define Ls rt<<1
15 #define Rs rt<<1|1
16 void update(int rt,int l,int r,int ql,int qr,int v){
17     if(ql<=l&&qr>=r){
18         tg[rt]+=v,tr[rt]+=v;
19         return;    
20     }
21     int mid=l+r>>1;
22     if(ql<=mid)update(Ls,l,mid,ql,qr,v);
23     if(qr>mid)update(Rs,mid+1,r,ql,qr,v);
24     tr[rt]=max(tr[Ls],tr[Rs])+tg[rt];
25     return;
26 }
27 int main(){
28     n=R(),d=R();
29     for(int i=1,x,y;i<=n;i++)
30         x=R(),y=R(),s[i]=(node){x-y,x+y},Y[i]=x+y;
31     sort(s+1,s+1+n,cmp),sort(Y+1,Y+1+n);
32     m=unique(Y+1,Y+1+n)-Y-1;
33     for(int l=1,r=1;r<=n;l++){
34         while(r<=n&&s[r].x-s[l].x<=d)
35             update(1,1,n,LB(r),UB(r),1),r++;
36         ans=max(ans,tr[1]);
37         update(1,1,n,LB(l),UB(l),-1);
38     }
39     cout<<ans<<endl;
40     return 0;
41 }
View Code

 

posted @ 2019-07-10 23:01  Chm_wt  阅读(230)  评论(0编辑  收藏  举报