Finding Hotels(牛客国庆集训派对Day7 )(2016ICPC青岛K)(K-D Tree)
生活随笔
收集整理的這篇文章主要介紹了
Finding Hotels(牛客国庆集训派对Day7 )(2016ICPC青岛K)(K-D Tree)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Finding Hotels
給定二維平面上nnn個點,每個點描述為x,y,cx, y, cx,y,c,x,yx, yx,y為坐標,ccc為該點的價值,
有mmm個詢問,每次詢問給x,y,cx, y, cx,y,c,要求,點的價值小于等于ccc的條件下,與x,yx, yx,y最近的且編號最小的點。
考慮K-D Tree,對K-D Tree的每個節點同時維護三個信息,L,R,D,U,Min_cL, R, D, U, Min\_cL,R,D,U,Min_c,然后減枝搜索即可。
#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 3e5 + 10;int ls[N], rs[N], n, m;int L[N], R[N], D[N], U[N], C[N], d[N];struct Res {int x, y, c, id; }s[N];bool cmp1(Res a, Res b) {return a.x < b.x; }bool cmp2(Res a, Res b) {return a.y < b.y; }void push_up(int rt) {L[rt] = R[rt] = s[rt].x;D[rt] = U[rt] = s[rt].y;C[rt] = s[rt].c;if (ls[rt]) {L[rt] = min(L[rt], L[ls[rt]]), R[rt] = max(R[rt], R[ls[rt]]);D[rt] = min(D[rt], D[ls[rt]]), U[rt] = max(U[rt], U[ls[rt]]);C[rt] = min(C[rt], C[ls[rt]]);}if (rs[rt]) {L[rt] = min(L[rt], L[rs[rt]]), R[rt] = max(R[rt], R[rs[rt]]);D[rt] = min(D[rt], D[rs[rt]]), U[rt] = max(U[rt], U[rs[rt]]);C[rt] = min(C[rt], C[rs[rt]]);} }int build(int l, int r) {if (l > r) {return 0;}int mid = l + r >> 1;double avx = 0, avy = 0, vax = 0, vay = 0;for (int i = l; i <= r; i++) {avx += s[i].x, avy += s[i].y;}avx /= r - l + 1, avy /= r - l + 1;for (int i = l; i <= r; i++) {vax += (avx - s[i].x) * (avx - s[i].x);vay += (avy - s[i].y) * (avy - s[i].y);}if (vax > vay) {nth_element(s + l, s + mid, s + r + 1, cmp1);d[mid] = 1;}else {nth_element(s + l, s + mid, s + r + 1, cmp2);d[mid] = 2;}ls[mid] = build(l, mid - 1), rs[mid] = build(mid + 1, r);push_up(mid);return mid; }ll ans_dis;int ans_id, ans;ll calc(int a, int b) {return 1ll * (s[a].x - s[b].x) * (s[a].x - s[b].x) + 1ll * (s[a].y - s[b].y) * (s[a].y - s[b].y); }ll calc_min(int a, int b) {ll ans = 0;if (L[a] >= s[b].x) {ans += (L[a] - s[b].x) * (L[a] - s[b].x); }if (R[a] <= s[b].x) {ans += (s[b].x - R[a]) * (s[b].x - R[a]);}if (D[a] >= s[b].y) {ans += (D[a] - s[b].y) * (D[a] - s[b].y);}if (U[a] <= s[b].y) {ans += (s[b].y - U[a]) * (s[b].y - U[a]);}return ans; }void query(int l, int r, int v) {if (l > r) {return ;}int mid = l + r >> 1;ll dis = calc(mid, v);if (s[mid].c <= s[v].c && (dis < ans_dis || (dis == ans_dis && s[mid].id < ans_id))) {ans_dis = dis, ans = mid, ans_id = s[mid].id;}if (l == r) {return ;}ll disl = calc_min(ls[mid], v), disr = calc_min(rs[mid], v);if (disl <= ans_dis && C[ls[mid]] <= s[v].c && disr <= ans_dis && C[rs[mid]] <= s[v].c) {if (disl < disr) {query(l, mid - 1, v);if (disr <= ans_dis) {query(mid + 1, r, v);}}else {query(mid + 1, r, v);if (disl <= ans_dis) {query(l, mid - 1, v);}}}else {if (disl <= ans_dis && C[ls[mid]] <= s[v].c) {query(l, mid - 1, v);}if (disr <= ans_dis && C[rs[mid]] <= s[v].c) {query(mid + 1, r, v);}} }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);int T;scanf("%d", &T);while (T--) {scanf("%d %d", &n, &m);for (int i = 1; i <= n; i++) {scanf("%d %d %d", &s[i].x, &s[i].y, &s[i].c);s[i].id = i;}build(1, n);int n1 = n;for (int i = 1; i <= m; i++) {n1++;scanf("%d %d %d", &s[n1].x, &s[n1].y, &s[n1].c);ans_dis = 0x3f3f3f3f3f3f3f3f, ans_id = 0x3f3f3f3f;query(1, n, n1);printf("%d %d %d\n", s[ans].x, s[ans].y, s[ans].c);}}return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Finding Hotels(牛客国庆集训派对Day7 )(2016ICPC青岛K)(K-D Tree)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 枸杞和桂圆一起泡水喝的功效与作用、禁忌和
- 下一篇: 单位根反演小记