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 ",ans); 76 }