Finals [Online Mirror, Div. 2] A. AI robots(線段樹動態開點)
阿新 • • 發佈:2018-12-11
題目大意:有n個機器人排成一排在一條直線上,第i個機器人在,同時它可以看到在的機器人,它的智商是。
如果兩個機器人可以相互看見對方,同時它們的智商差值小於等於k的話,它們就會發生一次談話。現在問你這n個機器人會發生幾次談話。
題目思路:首先我們來考慮如何知道兩個機器人是否能互相看見。我們可以先按從大到小對機器人進行排序,然後用一個線段樹記錄第 i 個節點是否有機器人,這樣我們就可以通過線段樹的區間查詢知道,對於第 i 個機器人,它可以看到多少個機器人。由於我們是動態加入機器人的,同時之前加入的機器人的 r 是要大於等於當前機器人的 r 的,所以當前機器人所能看到的機器人肯定也能看到當前的機器人。接下來我們再來考慮智商的約束條件,常規做法是線段樹再套一個線段樹,仍舊是通過區間查詢查出合適的機器人,但由於本題的記憶體只有256MB,樹套樹的空間接受不了,所以無法用樹套樹解決。解決本題有一個關鍵,就是k<=20,這樣每次我們只需要暴力遍歷40次即可,由於空間的限制原因,所以我們可以通過線段樹動態開點來維護智商為 qi 的機器人所在的位置,由於總的只有1e5個機器人,所以所耗費的空間會比樹套樹小很多。這樣就可以解決這個題了。
具體實現看程式碼:
#include <bits/stdc++.h> #define fi first #define se second #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pb push_back #define MP make_pair #define lowbit(x) x&-x #define clr(a) memset(a,0,sizeof(a)) #define _INF(a) memset(a,0x3f,sizeof(a)) #define FIN freopen("in.txt","r",stdin) #define IOS ios::sync_with_stdio(false) #define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int>pii; typedef pair<ll, ll>pll; const int MX = 1e5 + 7; const int mod = 1e9 + 7; const int N = 1e9; const int inf = 0x3f3f3f3f; int n, k, tot; int root[MX * 40], ls[MX * 40], rs[MX * 40]; ll sum[MX * 40]; struct node { int x, r, q; bool operator<(const node &A)const { return r > A.r; } } a[MX]; vector<int>h; int get_id(int x) { return lower_bound(h.begin(), h.end(), x) - h.begin() + 1; } void update(int p, int l, int r, int &rt) { if (!rt) rt = ++tot; sum[rt]++; if (l == r) return; int m = (l + r) >> 1; if (p <= m) update(p, l, m, ls[rt]); else update(p, m + 1, r, rs[rt]); } ll query(int L, int R, int l, int r, int rt) { if (!rt) return 0; if (L <= l && r <= R) return sum[rt]; int m = (l + r) >> 1; ll res = 0; if (L <= m) res += query(L, R, l, m, ls[rt]); if (R > m) res += query(L, R, m + 1, r, rs[rt]); return res; } int main() { //FIN; scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) { scanf("%d%d%d", &a[i].x, &a[i].r, &a[i].q); h.pb(a[i].q); h.pb(a[i].q - k); h.pb(a[i].q + k); } sort(a + 1, a + n + 1); sort(h.begin(), h.end()); h.erase(unique(h.begin(), h.end()), h.end()); ll ans = 0; for (int i = 1; i <= n; i++) { int st = a[i].q - k, ed = a[i].q + k; st = get_id(st); ed = get_id(ed); for (int j = st; j <= ed; j++) { if (!root[j]) continue; int L = max(0, a[i].x - a[i].r), R = min(N, a[i].x + a[i].r); ans += query(L, R, 0, N, root[j]); } a[i].q = get_id(a[i].q); update(a[i].x, 0, N, root[a[i].q]); } cout << ans << endl; return 0; }