CodeForces - 1046A AI robots(动态开点线段树)

版权声明:Why is everything so heavy? https://blog.csdn.net/lzc504603913/article/details/83930935

A. AI robots

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

In the last mission, MDCS has successfully shipped NN AI robots to Mars. Before they start exploring, system initialization is required so they are arranged in a line. Every robot can be described with three numbers: position (xixi), radius of sight (riri) and IQ (qiqi).

Since they are intelligent robots, some of them will talk if they see each other. Radius of sight is inclusive, so robot can see other all robots in range [xi−ri,xi+ri][xi−ri,xi+ri]. But they don't walk to talk with anybody, but only with robots who have similar IQ. By similar IQ we mean that their absolute difference isn't more than KK.

Help us and calculate how many pairs of robots are going to talk with each other, so we can timely update their software and avoid any potential quarrel.

Input

The first line contains two integers, numbers N(1≤N≤105)N(1≤N≤105) and K(0≤K≤20)K(0≤K≤20).

Next NN lines contain three numbers each xi,ri,qi(0≤xi,ri,qi≤109)xi,ri,qi(0≤xi,ri,qi≤109) — position, radius of sight and IQ of every robot respectively.

Output

Output contains only one number — solution to the problem.

Example

input

Copy

3 2
3 6 1
7 3 10
10 5 8

output

Copy

1

Note

The first robot can see the second, but not vice versa. The first robot can't even see the third. The second and the third robot can see each other and their IQs don't differ more than 2 so only one conversation will happen.

题意:二维空间互相覆盖的点有多少对。

解题思路:这是一个经典问题,先考虑一维的情况,直接扫描线即可。详见官方题解。这里提供另外一种思路,就是按照R排序,然后从大到小枚举,如果小的能看见大的,那么大的肯定也能看见小的。所以直接线段树查询即可。这里引入了 二维,由于第二位较小,直接暴力即可。这里一共要开 10^9 棵 范围为 0~1e9的线段树。所以要动态开点。实际上用到的点不多,所以完全可以开得下。因为是动态开点,所以离散化都省了。详见代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=100005;
const ll MAXQ=1e9+7;

struct point{
    ll x,r,q;
}Q[MAXN];

bool cmp(point &a,point &b){
    return a.r>b.r;
}
map<ll,int> mp;

int tot=0;
int ls[MAXN*40];
int rs[MAXN*40];
int sum[MAXN*40];
void update(int L,ll l,ll r,int &rt){
    if(rt==0)
        rt=++tot;
    if(l==r){
        sum[rt]++;
        return;
    }
    ll m=(l+r)/2;
    if(L<=m)
        update(L,l,m,ls[rt]);
    else
        update(L,m+1,r,rs[rt]);
    sum[rt]=sum[ls[rt]]+sum[rs[rt]];
}

int query(int L,int R,ll l,ll r,int rt){
    if(rt==0)
        return 0;
    if(L<=l&&r<=R)
        return sum[rt];
    ll m=(l+r)/2;
    int ans=0;
    if(L<=m)
        ans+=query(L,R,l,m,ls[rt]);
    if(R>m)
        ans+=query(L,R,m+1,r,rs[rt]);
    return ans;
}

int main()
{
    int N,K;
    scanf("%d%d",&N,&K);
    for(int i=0;i<N;i++)
        scanf("%lld%lld%lld",&Q[i].x,&Q[i].r,&Q[i].q);

    sort(Q,Q+N,cmp);//R排序
    ll ans=0;
    for(int i=0;i<N;i++)
    {
        for(ll j=Q[i].q-K;j<=Q[i].q+K;j++)//枚举第二维所有的线段树
        {
            if(!mp[j])
                continue;
            ans=ans+query(max(0ll,Q[i].x-Q[i].r),min(MAXQ,Q[i].x+Q[i].r),0,MAXQ,mp[j]);//暴力查询
        }
        update(Q[i].x,0,MAXQ,mp[Q[i].q]);//更新
    }
    cout<<ans<<endl;
    return 0;
}





猜你喜欢

转载自blog.csdn.net/lzc504603913/article/details/83930935
今日推荐