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; }
没有人不辛苦,只有人不喊疼