Codeforces 1045 G AI robots —— CDQ求三維+左右區間的數量

In the last mission, MDCS has successfully shipped N 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 (xi), radius of sight (ri) and IQ (qi).

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]. 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 K.

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) and K(0≤K≤20).

Next N lines contain three numbers each 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
inputCopy
3 2
3 6 1
7 3 10
10 5 8
outputCopy
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.

題意:

給你n個機器人的位置,信號範圍,智商。兩個機器人能交流的智商範圍k,兩個機器人能交流當且僅當他們的信號能夠相互到達且智商差距不大於k。問你有多少對機器人能夠交流。

題解:

好像帶修主席樹也能寫來着?但是很明顯CDQ更加簡單,因爲主席樹代碼太長且debug的平均時間過長,能不用主席樹就不用吧。但是一開始並沒有想到CDQ怎麼排序,還是看別人的代碼才知道還能這樣:
首先我們按照信號範圍從大到小排序,這樣就能保證從mid+1到r這個區間的機器人,他們信號所能到達的位置的那些l到mid的機器人的信號一定能到達他們。然後就是按照智商CDQ,這樣的話只需要用兩個指針維護智商能夠交流的範圍即可。最後樹狀數組記錄l到mid 的機器人他們的位置,查詢的話就查第i個機器人信號到達範圍即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
struct node
{
    ll x,R,q,l,r;
}ro[N],t;
ll num[N*3];
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int val)
{
    for(int i=x;i<N*3;i+=lowbit(i))
        num[i]+=val;
}
ll query(int x)
{
    ll ans=0;
    for(int i=x;i;i-=lowbit(i))
        ans+=num[i];
    return ans;
}
void clear(int x)
{
    for(int i=x;i<N*3;i+=lowbit(i))
        num[i]=0;
}
ll ans=0;
bool cmp1(node x,node y)
{
    return x.R>y.R;
}
bool cmp2(node x,node y)
{
    return x.q<y.q;
}
int n,all;
ll k;
void CDQ(int l,int r)
{
    if(l>=r)
        return ;
    int mid=l+r>>1;
    CDQ(l,mid),CDQ(mid+1,r);
    int p1,p2;
    p1=p2=l;
    for(int i=mid+1;i<=r;i++)
    {
        while(p2<=mid&&ro[p2].q<=ro[i].q+k)
            add(ro[p2++].x,1);
        while(p1<p2&&ro[p1].q<ro[i].q-k)
            add(ro[p1++].x,-1);
        ans+=(query(ro[i].r)-query(ro[i].l-1));
        if(ans<0)
            cout<<query(ro[i].r)<<" "<<query(ro[i].l-1)<<endl;
    }
    //cout<<l<<" "<<r<<" "<<ans<<endl;
    for(int i=p1;i<p2;i++)
        clear(ro[i].x);
    sort(ro+l,ro+r+1,cmp2);
}
ll pos[N*3];
int main()
{

    scanf("%d%lld",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld%lld",&ro[i].x,&ro[i].R,&ro[i].q),pos[++all]=ro[i].x-ro[i].R,pos[++all]=ro[i].x,pos[++all]=ro[i].x+ro[i].R;
    sort(pos+1,pos+1+all);
    all=unique(pos+1,pos+1+all)-pos-1;
    for(int i=1;i<=n;i++)
        ro[i].l=lower_bound(pos+1,pos+1+all,ro[i].x-ro[i].R)-pos,ro[i].r=lower_bound(pos+1,pos+1+all,ro[i].x+ro[i].R)-pos,ro[i].x=lower_bound(pos+1,pos+1+all,ro[i].x)-pos;
    sort(ro+1,ro+1+n,cmp1);
    CDQ(1,n);
    printf("%lld\n",ans);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章