• 【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;
    }
    
  • 相关阅读:
    二十三、Android源代码是这样搞到的(图解)
    defer用途
    vscode中go插件配置
    peewee外键性能问题
    bootstrap-select属性
    go环境变量及build文件
    peewee在flask中的配置
    python元类
    Java静态方法、单例模式区别
    Java实现list清除重复的字符串
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11845775.html
Copyright © 2020-2023  润新知