In the lattice points of the coordinate line there are n radio stations, the i-th of which is described by three integers:
- xi — the coordinate of the i-th station on the line,
- ri — the broadcasting range of the i-th station,
- fi — the broadcasting frequency of the i-th station.
We will say that two radio stations with numbers i and j reach each other, if the broadcasting range of each of them is more or equal to the distance between them. In other words min(ri, rj) ≥ |xi - xj|.
Let's call a pair of radio stations (i, j) bad if i < j, stations i and j reach each other and they are close in frequency, that is, |fi - fj| ≤ k.
Find the number of bad pairs of radio stations.
The first line contains two integers n and k (1 ≤ n ≤ 105, 0 ≤ k ≤ 10) — the number of radio stations and the maximum difference in the frequencies for the pair of stations that reach each other to be considered bad.
In the next n lines follow the descriptions of radio stations. Each line contains three integers xi, ri and fi (1 ≤ xi, ri ≤ 109, 1 ≤ fi ≤ 104) — the coordinate of the i-th radio station, it's broadcasting range and it's broadcasting frequency. No two radio stations will share a coordinate.
Output the number of bad pairs of radio stations.
3 2 1 3 10 3 2 5 4 10 8
1
3 3 1 3 10 3 2 5 4 10 8
2
5 1 1 3 2 2 2 4 3 2 1 4 2 1 5 3 3
2
5 1 1 5 2 2 5 4 3 5 1 4 5 1 5 5 3
5
题解:two-pointer枚举右端点(显然按x排序),那左端点的指针呢?
左端点用另一种排序方式:按x+r排序,即能到的最远的x排序,这样就可以two-pointer了
对于一个右端点,我们通过暴力枚举f-k到f+k之间的数查找,然后就只需要查找x[j]>=x[i]-r[i]的即可
由于x特别大,用动态开点线段树直接解决
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100010;
const int MAXM = MAXN * 30;
const int MAXF = 10010;
const int INF = 1e9;
inline int read()
{
int sc = 0; char ch = getchar();
while( ch < '0' || ch > '9' ) ch = getchar();
while( ch >= '0' && ch <= '9' ) sc = sc * 10 + ch - '0', ch = getchar();
return sc;
}
int ls[MAXM], rs[MAXM], v[MAXM], root[MAXF], n, m, rank[MAXN], tot;
long long ans;
struct node
{
int x, r, f;
bool operator < ( const node & b ) const { return x < b.x; }
}a[MAXN];
bool cmp(int x, int y) { return a[ x ].x + a[ x ].r < a[ y ].x + a[ y ].r; }
inline void modify(int &x, int l, int r, int pos, int val)
{
if( !x ) x = ++tot;
v[ x ] += val;
if( l == r ) return ;
int mid = l + r >> 1;
if( pos <= mid ) modify( ls[ x ], l, mid, pos, val );
else modify( rs[ x ], mid + 1, r, pos, val );
}
inline int query(int x, int l, int r, int pos)
{
if( !x ) return 0;
if( l >= pos ) return v[ x ];
int mid = l + r >> 1;
if( pos <= mid ) return query( ls[ x ], l, mid, pos ) + v[ rs[ x ] ];
return query( rs[ x ], mid + 1, r, pos );
}
int main()
{
n = read(), m = read();
for( int i = 1 ; i <= n ; i++ ) a[ i ].x = read(), a[ i ].r = read(), a[ i ].f = read(), rank[ i ] = i;
sort( a + 1, a + n + 1 ); sort( rank + 1, rank + n + 1, cmp );
for( int i = 1, j = 1 ; i <= n ; i++ )
{
while( j <= n && a[ rank[ j ] ].x + a[ rank[ j ] ].r < a[ i ].x ) modify( root[ a[ rank[ j ] ].f ], 1, INF, a[ rank[ j ] ].x, -1 ), j++;
for( int k = max( 1, a[ i ].f - m ) ; k <= min( 10000, a[ i ].f + m ) ; k++ ) ans += query( root[ k ], 1, INF, max( a[ i ].x - a[ i ].r , 1 ) );
modify( root[ a[ i ].f ], 1, INF, a[ i ].x, 1 );
}
cout << ans << endl;
return 0;
}