CF1045G AI robots(CDQ分治)

关注一下互相看到的问题,因为只有这样才是一对。我们按r排序,这样只需要关注一个点和他左边点的关系

因为如果它能看到左边的,左边的一定能看到他。之后我们要求的是一个二维数点的模型,这种模型我们考虑用cdq分治来解决。

如果能把智商排序,那么这样的用双指针就能维护全部,但是这题不能直接对整段排序,因为我们要求r的关系。

因此解决方法可以是先做后排序,或者按mid分成两段排序。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+10;
ll tr[N];
int n,k;
struct node{
    int x,r,q;
}s[N],s1[N];
int lowbit(int x){
    return x&-x;
}
void add(int x,int c){
    int i;
    for(i=x;i<N;i+=lowbit(i)){
        tr[i]+=c;
    }
}
ll sum(int x){
    int i;
    ll res=0;
    for(i=x;i;i-=lowbit(i)){
        res+=tr[i];
    }
    return res;
}
vector<ll> num;
bool cmpa(node a,node b){
    return a.r>b.r;
}
bool cmpb(node a,node b){
    return a.q<b.q;
}
int find(int x){
    return lower_bound(num.begin(),num.end(),x)-num.begin()+1;
}
ll ans=0;
void cdq(int l,int r){
    if(l==r)
        return ;
    int mid=l+r>>1;
    cdq(l,mid);
    cdq(mid+1,r);
    int i;
    int L=l,R=l-1;
    for(int i=mid+1;i <= r;i++){
        while(L<=mid&&s[i].q-s[L].q>k) add(find(s[L++].x),-1);
        while(R<mid&&s[R+1].q-s[i].q<=k) add(find(s[++R].x),1);
        ans +=sum(find(s[i].x+s[i].r))-sum(find(s[i].x-s[i].r)-1);
    }
    for(int i=L;i<=R;i++) add(find(s[i].x),-1);
    sort(s+l,s+r+1,cmpb);
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>k;
    int i;
    for(i=1;i<=n;i++){
        cin>>s[i].x>>s[i].r>>s[i].q;
        num.push_back(s[i].x);
        num.push_back(s[i].x-s[i].r);
        num.push_back(s[i].x+s[i].r);
    }
    sort(num.begin(),num.end());
    num.erase(unique(num.begin(),num.end()),num.end());
    sort(s+1,s+1+n,cmpa);
    for(i=1;i<=n;i++)
        s1[i]=s[i];
    cdq(1,n);
    cout<<ans<<endl;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/13697859.html