T1:

数轴上有 n 个点,第 i 个点的坐标为 xi,权值为 wi。两个点 i,j 之间存在一条边当且仅当 abs(xi-xj)>=wi+wj。
你需要求出这张图的最大团的点数。
(团就是两两之间有边的顶点集合)
【输入格式】
输入文件clique.in
第一行一个整数 n,接下来 n 行每行两个整数 xi,wi。
【输出格式】
输出文件clique.out
输出一行一个整数,表示最大团的点数。
【样例输入】
4
2 3
3 1
6 1
0 2
【样例输出】
3
【数据范围】
对于 20%的数据,n<=10。
对于 60%的数据,n<=1000。
对于 100%的数据,n<=2000000<=|xi|,wi<=10^9

  本弱看到这道题时第一反应肯定是n^2连边也过不了啊,所以肯定有巧妙的方法来解这道题废话我们可以看到,有边相连的2个点的要求是abs(xi-xj)>=wi+wj,也就是说如果i和j有边,那么从xi-wi到xi+wi和xj-wj到xj+wj这两段区间是没有重合部分的,那么我们把每个点都扩成一段区间,最多的不重合的区间数就是最大团的点数,因为互不重合就代表了两两之间有边。

代码:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdio>
 4 using namespace std;
 5 const int maxn=200004;
 6 int n;
 7 struct zhw{
 8     int l,r;
 9     friend bool operator <(zhw a,zhw b)
10     {
11         return  a.r<b.r||(a.r==b.r&&a.l>b.l);
12     }
13 }a[maxn];
14 int x,w,l,r;
15 int main()
16 {
17     freopen("clique.in","r",stdin);
18     freopen("clique.out","w",stdout);
19     scanf("%d",&n);
20     for(int i=1;i<=n;++i)
21     {
22         scanf("%d%d",&x,&w);
23         a[i].l=x-w,a[i].r=x+w;
24     }
25     sort(a+1,a+n+1);
26     int pos=a[1].r,ans=1;
27     for(int i=1;i<=n;++i)
28     {
29         if(a[i].l>=pos)ans++,pos=a[i].r;
30     }
31     printf("%d",ans);
32     fclose(stdin);fclose(stdout);
33     return 0;
34 } 
View Code

相关文章: