题目链接:http://codeforces.com/contest/1046/problem/A
题目大意:有n个机器人排成一排在一条直线上,第i个机器人在,同时它可以看到在的机器人,它的智商是。
如果两个机器人可以相互看见对方,同时它们的智商差值小于等于k的话,它们就会发生一次谈话。现在问你这n个机器人会发生几次谈话。
题目思路:首先我们来考虑如何知道两个机器人是否能互相看见。
我们可以先按从大到小对机器人进行排序,然后用一个线段树记录第 i 个节点是否有机器人,这样我们就可以通过线段树的区间查询知道,对于第 i 个机器人,它可以看到多少个机器人。
由于我们是动态加入机器人的,同时之前加入的机器人的 r 是要大于等于当前机器人的 r 的,所以当前机器人所能看到的机器人肯定也能看到当前的机器人。
接下来我们再来考虑智商的约束条件,常规做法是线段树再套一个线段树,仍旧是通过区间查询查出合适的机器人,但由于本题的内存只有256MB,树套树的空间接受不了,所以无法用树套树解决。
解决本题有一个关键,就是k<=20,这样每次我们只需要暴力遍历40次即可,由于空间的限制原因,所以我们可以通过线段树动态开点来维护智商为 qi 的机器人所在的位置,由于总的只有1e5个机器人,所以所耗费的空间会比树套树小很多。这样就可以解决这个题了。
具体实现看代码:
#include
#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)<<"]"<pii;
typedef pairpll;
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];
vectorh;
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;
}