【cf1046】A. AI robots(动态开点线段树)

传送门

题意:
坐标轴上有(n)个机器人,每个机器人带有属性(x,r,q),分别表示位置、可视半径以及智商。
现在定义智商相近为两个机器人的智商差的绝对值不超过$K。
现在问有多少对机器人,他们在互相的可视范围内并且智商相近。

思路:
一开始没注意到互相在对面的可视范围内,以为是主席树模板题。。。

  • 注意到(Kleq 20),所以总的有用的智商值为(40*n)个。
  • 那么我们可以采用动态开点的方法,对于每个智商值,储存存在的区间的位置,这样可以节约空间。
  • 对于互相在对方可视范围内,可以先按(r)从大到小排序,然后依次处理,当前位置为(x_i),那么在([x_i-r_i,x_i+r_i)内的机器人都是合法的。
  • 那么对于每个机器人,暴力每个智商值,查询在对应区间范围内的机器人个数即可。

时间复杂度约为(O(nklogn)),空间复杂度也因为动态开点优化到了(O(nlogn))
代码如下:

/*
 * Author:  heyuhhh
 * Created Time:  2019/11/12 20:42:29
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '
'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '
'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 25;

int n, k;
struct node{
    int x, r, q;
    bool operator < (const node &A) const{
        return r > A.r;
    }
}a[N];

unordered_map <int, int> mp;
int tot;
int rt[N * 35], ls[N * 35], rs[N * 35], sum[N * 35];

void upd(int &o, int l, int r, int p, int v) {
    if(!o) o = ++tot;   
    if(l == r) {
        sum[o] += v;
        return;
    }
    int mid = (l + r) >> 1;
    if(p <= mid) upd(ls[o], l, mid, p, v);
    else upd(rs[o], mid + 1, r, p, v);
    sum[o] = sum[ls[o]] + sum[rs[o]];
}

int query(int o, int l, int r, int L, int R) {
    if(!o) return 0;
    if(L <= l && r <= R) {
        return sum[o];   
    }
    int res = 0, mid = (l + r) >> 1;
    if(L <= mid) res += query(ls[o], l, mid, L, R);
    if(R > mid) res += query(rs[o], mid + 1, r, L, R);
    return res;
}

void run(){
    for(int i = 1; i <= n; i++) cin >> a[i].x >> a[i].r >> a[i].q;
    sort(a + 1, a + n + 1);
    ll ans = 0;
    for(int i = 1; i <= n; i++) {
        int l = max(0, a[i].x - a[i].r);
        int r = a[i].x + a[i].r;
        int L = max(0, a[i].q - k);
        int R = a[i].q + k;  
        for(int j = L; j <= R; j++) {
            if(mp.find(j) == mp.end()) continue;
            ans += query(rt[mp[j]], 0, INF, l, r);
        } 
        if(mp.find(a[i].q) == mp.end()) mp[a[i].q] = ++tot;
        upd(rt[mp[a[i].q]], 0, INF, a[i].x, 1);
    }
    cout << ans << '
';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n >> k) run();
	return 0;
}
原文地址:https://www.cnblogs.com/heyuhhh/p/11845775.html