CF762E Radio stations
很明显是一道偏序问题,我们先列出满足条件的台之间的关系。
\[\min(r_i,r_j)\ge|x_i-x_j|
\]
\[|f_i-f_j|\le k
\]
这看起来好像是两条式子,但是不能直接使用二维偏序解决,因为其中含有取最小值操作,所以无法直接使用二维偏序处理。
那么就可以尝试考虑三维偏序了。
先转换一下式子,拆掉绝对值。
\[r_j\le r_i
\]
\[f_j-k\le f_i\le f_j+k
\]
\[x_j-r_j\le x_i \le x_j+r_j
\]
我们首先对于第一维,可以先把最小值问题处理了。我们按照半径长度从小到大排序进行处理即可,对应第一条式子。
对于第二维,我们用 CDQ 以后,对频率进行排序即可,对应第二条式子。
对于第三维,使用树状数组区间修改即可。由于需要使用树状数组,这一部分需要提前离散化。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k,ans,tmp[300005],cnt;
struct P{
int x,b,f,l,r;//分别记录位置,半径,频率, 在可传递范围的左右边界
}a[100005];
bool cmp(P a,P b){
return a.b<b.b;//先按照半径排序
}
bool cmp2(P a,P b){
return a.f<b.f;//按照频率排序
}
struct BT{
int c[200005];
void init(){
memset(c,0,sizeof(c));
}
int lowbit(int x){
return x&-x;
}
void add(int x,int y){
for(int i=x;i<=n;i+=lowbit(i))c[i]+=y;
}
int query(int x){
int ans=0;
for(int i=x;i;i-=lowbit(i))ans+=c[i];
return ans;
}
int query(int l,int r){
return query(r)-query(l-1);
}
}bit;
void CDQ(int l,int r){
if(l==r)return;
int mid=l+r>>1;
CDQ(l,mid),CDQ(mid+1,r);
sort(a+l,a+mid+1,cmp2),sort(a+mid+1,a+r+1,cmp2);
int L=mid+1,R=mid+1;
for(int i=l;i<=mid;i++){
while(R<=r&&a[R].f-a[i].f<=k)bit.add(a[R].x,1),R++;//通过频率关系确定范围
while(L<=r&&a[i].f-a[L].f>k)bit.add(a[L].x,-1),L++;
ans+=bit.query(a[i].l,a[i].r);
}
for(int i=L;i<R;i++)bit.add(a[i].x,-1);
}
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].b>>a[i].f;
a[i].l=a[i].x-a[i].b;
a[i].r=a[i].x+a[i].b;
tmp[++cnt]=a[i].x;
}
sort(tmp+1,tmp+cnt+1);//离散化
cnt=unique(tmp+1,tmp+cnt+1)-tmp-1;
for(int i=1;i<=n;i++){
a[i].x=lower_bound(tmp+1,tmp+cnt+1,a[i].x)-tmp;
a[i].l=lower_bound(tmp+1,tmp+cnt+1,a[i].l)-tmp;
a[i].r=upper_bound(tmp+1,tmp+cnt+1,a[i].r)-tmp-1;
}
sort(a+1,a+n+1,cmp);
CDQ(1,n);
cout<<ans;
return 0;
}

浙公网安备 33010602011771号