传送门
文章目录
- 题意
- 思路:
题意
有nnn个电台,对于每个电台iii有三个参数xi,ri,fix_i,r_i,f_ixi,ri,fi,分别指他们的坐标、作用半径、频率。如果两个电台频率差值在kkk以内,并且他们的作用范围都能覆盖到彼此,那么称这两个电台互相干扰,问这nnn个站台中互相干扰的站台有多少对。
$1\le n\le1e5,0\le k\le 10,1\le x_i,r_i\le 1e9,1\le f_i\le 1e4 $
思路:
首先将问题简化一下,题面无非就是求满足以下两个条件的对数:
(1)∣xi−xj∣≤min(ri,rj)(1)|x_i-x_j|\le min(r_i,r_j)(1)∣xi−xj∣≤min(ri,rj)
(2)∣fi−fj∣≤k(2)|f_i-f_j|\le k(2)∣fi−fj∣≤k
看起来很cdqcdqcdq,考虑怎么分三维。
首先绝对值和取minminmin肯定是要优先考虑的,并且如果我们确定了rrr的话,这个貌似就变成了个区间查询的问题,所以我们第一维按照rrr从大到小排序,这样rrr的值[l,mid]>[mid+1,r][l,mid]>[mid+1,r][l,mid]>[mid+1,r],算左区间对右区间的贡献的时候,左区间的xix_ixi直接加入答案中,右区间貌似直接查询一下[xj−rj,xj+rj][x_j-r_j,x_j+r_j][xj−rj,xj+rj]区间内的个数即可,离散化+树状数组完全可以解决,这样我们就定下来了第三维。那么第二维就剩下fff了,我们在第三维查询区间内个数的时候,需要满足∣fi−fj∣≤k|f_i-f_j|\le k∣fi−fj∣≤k,也就是说树状数组存下来的需要是合法的fff,所以我们考虑整个指针代表的左区间[x,i][x,i][x,i],由于第二维fi<fjf_i<f_jfi<fj成立,所以对于fjf_jfj我们需要保证fx+k>=fjf_x+k>=f_jfx+k>=fj最小的xxx即可,显然这个具有单调性,动态维护一下。
但是很快你就会发现不对劲,因为∣fi−fj∣≤k|f_i-f_j|\le k∣fi−fj∣≤k是带绝对值的!所以你只考虑左边≤fj\le f_j≤fj是不对的,你还需要维护一个指针yyy,这个需要找到fy−k<=fjf_y-k<=f_jfy−k<=fj的最大的yyy位置。之后就得到了区间[x,y][x,y][x,y],现在就可以查询啦~
由于第二维保证有序,所以jjj右移的时候,x,yx,yx,y也是单调不减的,可以保证复杂度。
还有要注意,离散化的时候,离散化得到的l,rl,rl,r需要跟iii下表绑定,也就是放到结构体里面,闲的没事开了个数组存,结果cdqcdqcdq的时候改变了顺序wawawa了半天。。。
复杂度O(nlog2n)O(nlog^2n)O(nlog2n)
// Problem: E. Radio stations
// Contest: Codeforces - Educational Codeforces Round 17
// URL: https://codeforces.com/problemset/problem/762/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
#define lowbit(x) (x&(-x))
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n,k;
PII p[N];
int tr[N],se;
LL ans;
struct Node {int x,y,z,l,r;bool operator < (const Node &W) const {return mk(-x,mk(y,z))<mk(-W.x,mk(W.y,W.z));}
}q[N],a[N];
vector<int>v;int find(int x) {return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}void add(int x,int c) {for(int i=x;i<=se;i+=lowbit(i)) tr[i]+=c;
}int sum(int x) {int ans=0;for(int i=x;i;i-=lowbit(i)) ans+=tr[i];return ans;
}bool cmp(Node a,Node b) {return a.y<b.y;
}void cdq(int l,int r) {if(l>=r) return;int mid=(l+r)>>1;cdq(l,mid); cdq(mid+1,r);int ls=l,rs=l;for(int i=mid+1;i<=r;i++) {while(ls<=mid&&q[ls].y+k<q[i].y) add(q[ls].z,-1),ls++;while(rs<=mid&&q[rs].y-k<=q[i].y) add(q[rs].z,1),rs++;ans+=sum(q[i].r)-sum(q[i].l-1);}while(ls<rs) add(q[ls].z,-1),ls++;int i=l,j=mid+1,cnt=0;while(i<=mid&&j<=r) {if(q[i].y<=q[j].y) a[++cnt]=q[i++];else a[++cnt]=q[j++];}while(i<=mid) a[++cnt]=q[i++];while(j<=r) a[++cnt]=q[j++];for(int i=1;i<=cnt;i++) q[l+i-1]=a[i];
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);scanf("%d%d",&n,&k);for(int i=1;i<=n;i++) {int x,y,z; scanf("%d%d%d",&x,&y,&z);q[i]={y,z,x};v.pb(x-y); v.pb(x+y); v.pb(x);}sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end());se=v.size();sort(q+1,q+1+n);for(int i=2;i<=n;i++) if(q[i].x==q[i-1].x&&q[i].y==q[i-1].y&&q[i].z==q[i-1].z) while(1);for(int i=1;i<=n;i++) {q[i].l=find(q[i].z-q[i].x),q[i].r=find(q[i].z+q[i].x);q[i].z=find(q[i].z);}cdq(1,n);cout<<ans<<endl;return 0;
}
/*
k=1
r f x
x y z
10 8 4
3 10 1
2 5 31 2 0**
1 3 1**
4 5 1**
1 5 3**
*/// #include <bits/stdc++.h>
// using namespace std;
// typedef long long ll;
// #define rep(i, a, b) for(int i=(a), i##up=(b); i<=i##up; ++i)
// #define repf(i, a) for(int i=1, i##up=(a); i<=i##up; ++i)
// #define rrep(i, a, b) for(int i=(a), i##dn=(b); i>=i##dn; --i)
// #define repe(e, u) for(int e=head[u]; e; e=nxt[e])
//
// int read() {// int t=0, f=1; char c;// while(!isdigit(c=getchar())) f=c^45;// while(isdigit(c)) t=(t<<1)+(t<<3)+(c^48), c=getchar();// return f? t: -t;
// }
//
// const int N=1e5+10, inf=1e9;
//
// int n, k;
// ll ans;
//
// struct BIT {// #define lb(x) ((x)&-(x))// static const int X=3e5;// int c[X+10], tik[X+10], tim;// inline void modify(int x, int v=1) {// for(; x<=X; x+=lb(x)) if(tik[x]==tim) c[x]+=v; else tik[x]=tim, c[x]=v;// }// inline int query(int x, int v=0) {// for(; x; x^=lb(x)) if(tik[x]==tim) v+=c[x]; else tik[x]=tim, c[x]=0;// return v;// }// inline void clear() { tim++; }
// }tre;
//
// int px[N*3], siz;
// inline int find(int x) {// return lower_bound(px+1, px+1+siz, x)-px;
// }
// struct state {// int x, r, f, le, ri;// state() {}// state(int a, int b, int c): x(a), r(b), f(c) {}// inline void get() {// x=read(), r=read(), f=read();// le=x-r, ri=x+r;// px[++siz]=x, px[++siz]=le, px[++siz]=ri;// }// inline void reset() {// x=find(x), le=find(le), ri=find(ri);// }
// }st[N];
// bool cmpr(state a, state b) {// if(a.r==b.r) return a.f<b.f||a.f==b.f&&a.x<b.x;// return a.r>b.r;
// }
// bool cmpf(state a, state b) {// return a.f<b.f;
// }
//
// void sol(int le, int ri) {// if(le==ri) return;// int mid=le+ri>>1;// sol(le, mid), sol(mid+1, ri), tre.clear();// sort(st+le, st+mid+1, cmpf), sort(st+mid+1, st+ri+1, cmpf);// int pi_dn=le, pi_up=le, pj=mid+1;// while(pj<=ri) {// while(st[pj].f-st[pi_dn].f>k&&pi_dn<=mid) tre.modify(st[pi_dn++].x, -1);// while(st[pi_up].f-st[pj].f<=k&&pi_up<=mid) tre.modify(st[pi_up++].x);// ans+=tre.query(st[pj].ri)-tre.query(st[pj].le-1), pj++;// }
// }
//
// int main() {// n=read(), k=read();// repf(i, n) st[i].get();// sort(px+1, px+1+siz), siz=unique(px+1, px+1+siz)-px-1;// repf(i, n) st[i].reset();// sort(st+1, st+1+n, cmpr);// sol(1, n);// printf("%lld", ans);
// }