• 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
    ",ans);
    76 }
  • 相关阅读:
    Spring源码IOC容器初始化过程【2】
    《MySQL实战45讲》个人笔记实战篇
    Spring源码Xml Bean解析注册过程【3】
    Spring源码循环依赖用实例证明去掉二级缓存会出现什么问题【7】
    Spring源码Bean实例化过程【5】
    git删除已push记录
    3.多线程面试
    4.JVM面试题
    6.Linux文本处理
    二.实践中发现的命令问题
  • 原文地址:https://www.cnblogs.com/refun/p/10483364.html
Copyright © 2020-2023  润新知