CF1045G:AI robots(CDQ分治)

Description

火星上有$n$个机器人排成一行,第$i$个机器人的位置为$x_i$,视野为$r_i​$,智商为$q_i​$。我们认为第$i$个机器人可以看到的位置是$[x_i−r_i,x_i+r_i]$。如果一对机器人相互可以看到,且它们的智商$q_i$的差距不大于$k$,那么它们会开始聊天。 为了防止它们吵起来,请计算有多少对机器人可能会聊天。

Input

第一行读入$n,k$。

后面$n$行每行$x_i,r_i,q_i$。

Output

一行答案。

Sample Input

3 2
3 6 1
7 3 10
10 5 8

Sample Output

1

Solution

当时比赛的时候$sugar$给我讲了个平衡树做法还没写出来……

不过$CDQ$做起来的确简单……

先把机器人按视野半径从大到小排序,那么后面的如果能看到前面的,那么前面的一定也能看到后面的,方便我们$CDQ$用前面的去更新后面的性质。

$CDQ$里面按智商排序。可以发现对于当前$CDQ$处理的右半边,随着右边指针右移,左边合法的智商范围是一个长度不变且单调向右的区间,所以可以用单调队列优化。

里面$sort$并不会影响复杂度……因为就算写了归并复杂度还是$nlog^2n$。

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #define N (300009)
 6 #define LL long long
 7 using namespace std;
 8 
 9 struct Que{int x,r,q;}a[N];
10 int n,k,b_num,b[N],c[N];
11 LL ans;
12 
13 inline int read()
14 {
15     int x=0,w=1; char c=getchar();
16     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
17     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
18     return x*w;
19 }
20 
21 bool cmp1(Que a,Que b)
22 {
23     return a.r>b.r;
24 }
25 
26 bool cmp2(Que a,Que b)
27 {
28     return a.q<b.q;
29 }
30 
31 int getid(int x)
32 {
33     return lower_bound(b+1,b+b_num+1,x)-b;
34 }
35 
36 void Update(int x,int k)
37 {
38     for (; x<=b_num; x+=(x&-x)) c[x]+=k;
39 }
40 
41 int Query(int x)
42 {
43     int ans=0;
44     for (; x; x-=(x&-x)) ans+=c[x];
45     return ans;
46 }
47 
48 void CDQ(int l,int r)
49 {
50     if (l==r) return;
51     int mid=(l+r)>>1;
52     CDQ(l,mid); CDQ(mid+1,r);
53     int L=l,R=l-1;
54     for (int i=mid+1; i<=r; ++i)
55     {
56         while (R+1<=mid && a[R+1].q<=a[i].q+k) Update(getid(a[R+1].x),1), ++R;
57         while (L<=mid && a[L].q<a[i].q-k) Update(getid(a[L].x),-1), ++L;
58         ans+=Query(getid(a[i].x+a[i].r))-Query(getid(a[i].x-a[i].r)-1);
59     }
60     for (int i=L; i<=R; ++i) Update(getid(a[i].x),-1);
61     sort(a+l,a+r+1,cmp2);
62 }
63 
64 int main()
65 {
66     n=read(); k=read();
67     for (int i=1; i<=n; ++i)
68     {
69         int x=read(),r=read(),q=read();
70         b[++b_num]=x; b[++b_num]=x+r; b[++b_num]=x-r;
71         a[i]=(Que){x,r,q};
72     }
73     sort(b+1,b+b_num+1); b_num=unique(b+1,b+b_num+1)-b-1;
74     sort(a+1,a+n+1,cmp1); CDQ(1,n);
75     printf("%lld\n",ans);
76 }
posted @ 2019-03-06 15:09  Refun  阅读(245)  评论(0编辑  收藏  举报