2648: SJY摆棋子

2648: SJY摆棋子

https://www.lydsy.com/JudgeOnline/problem.php?id=2648

分析:   

  k-d tree 模板题。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4  
  5 inline int read() {
  6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
  7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
  8 }
  9 
 10 const int N = 500010;
 11 const int DIM = 2;
 12 const int INF = 1e9;
 13  
 14 #define lc T[rt].ch[0]
 15 #define rc T[rt].ch[1]
 16  
 17 struct Point {
 18     int x[2];
 19     Point() {x[0] = 0,x[1] = 0;}
 20     Point(int a,int b) {x[0] = a,x[1] = b;}
 21 }P[N];
 22 struct KD_Tree {
 23     int ch[2],mn[2],mx[2];
 24     Point p;
 25 }T[N<<1];
 26 int Cur,CntNode,Ans,Root;
 27  
 28 inline bool cmp(Point a,Point b) {
 29     return a.x[Cur] < b.x[Cur];
 30 }
 31 inline void pushup(int rt) {
 32     for (int i=0; i<DIM; ++i) {
 33         if (lc) T[rt].mn[i] = min(T[rt].mn[i],T[lc].mn[i]), T[rt].mx[i] = max(T[rt].mx[i],T[lc].mx[i]);
 34         if (rc) T[rt].mn[i] = min(T[rt].mn[i],T[rc].mn[i]), T[rt].mx[i] = max(T[rt].mx[i],T[rc].mx[i]); // -- rc - lc
 35     }
 36 }
 37 inline void NewNode(int rt,Point p) {
 38     T[rt].p = p;
 39     T[rt].mn[0] = T[rt].mx[0] = p.x[0];
 40     T[rt].mn[1] = T[rt].mx[1] = p.x[1];
 41 }
 42 int build(int l,int r,int cd) { // cd -- cur dimensions
 43     if (l > r) return 0;
 44     int m = (l + r) >> 1,rt = m;
 45     Cur = cd; nth_element(P+l, P+m, P+r+1, cmp);
 46     NewNode(rt,P[m]);
 47     lc = build(l, m-1, cd^1);
 48     rc = build(m+1, r, cd^1);
 49     pushup(rt);
 50     return rt;
 51 }
 52 void Insert(Point p,int &rt,int cd) {
 53     if (!rt) {
 54         NewNode(rt = ++CntNode,p);return ;
 55     }
 56     if (p.x[cd] <= T[rt].p.x[cd]) Insert(p, lc, cd^1);
 57     else Insert(p, rc, cd^1);
 58     pushup(rt);
 59 }
 60 inline int dist(Point a,KD_Tree b) {
 61     int dis = 0;
 62     if (a.x[0] < b.mn[0]) dis += b.mn[0] - a.x[0];
 63     if (a.x[0] > b.mx[0]) dis += a.x[0] - b.mx[0];
 64     if (a.x[1] < b.mn[1]) dis += b.mn[1] - a.x[1];
 65     if (a.x[1] > b.mx[1]) dis += a.x[1] - b.mx[1];
 66     return dis;
 67 }
 68 inline int dis(Point a,Point b) {
 69     return abs(a.x[0] - b.x[0]) + abs(a.x[1] - b.x[1]);
 70 }
 71 void query(Point p,int rt) {
 72     Ans = min(Ans,dis(p,T[rt].p)); // -- !!
 73     int dl = lc ? dist(p,T[lc]) : INF;
 74     int dr = rc ? dist(p,T[rc]) : INF;
 75     if (dl < dr) {
 76         if (dl < Ans) query(p,lc);
 77         if (dr < Ans) query(p,rc);
 78     }
 79     else {
 80         if (dr < Ans) query(p,rc);
 81         if (dl < Ans) query(p,lc);
 82     }
 83 }
 84 int main() {
 85     int n = read(),m = read();
 86     CntNode = n; // --- !!!
 87     for (int i=1; i<=n; ++i) 
 88         P[i].x[0] = read(),P[i].x[1] = read();
 89     Root = build(1,n,1);
 90     while (m--) {
 91         int opt = read(),x = read(),y = read();
 92         if (opt == 1) Insert(Point(x,y),Root,1);
 93         else {
 94             Ans = INF;
 95             query(Point(x,y),Root);
 96             printf("%d
",Ans);
 97         }
 98     }
 99     return 0;
100 }
View Code

luogu上需要拍扁重构,否则会T,而bzoj上拍扁重构却不如不拍扁重构跑得快

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4  
  5 inline int read() {
  6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
  7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
  8 }
  9 
 10 const int N = 500010;
 11 const int DIM = 2;
 12 const int INF = 1e9;
 13  
 14 #define alpha 0.75
 15 #define lc T[rt].ch[0]
 16 #define rc T[rt].ch[1]
 17  
 18 struct Point {
 19     int x[2];
 20     Point() {x[0] = 0,x[1] = 0;}
 21     Point(int a,int b) {x[0] = a,x[1] = b;}
 22 }P[N<<1];
 23 struct KD_Tree {
 24     int ch[2],mn[2],mx[2],sz;
 25     Point p;
 26 }T[N<<1];
 27 int sk[N],Top,Cur,CntNode,Ans,Root;
 28  
 29 inline bool cmp(Point a,Point b) {
 30     return a.x[Cur] < b.x[Cur];
 31 }
 32 inline void pushup(int rt) {
 33     T[rt].sz = T[lc].sz + T[rc].sz + 1; //-- +1!!! 
 34     for (int i=0; i<DIM; ++i) {
 35         if (lc) T[rt].mn[i] = min(T[rt].mn[i],T[lc].mn[i]), T[rt].mx[i] = max(T[rt].mx[i],T[lc].mx[i]);
 36         if (rc) T[rt].mn[i] = min(T[rt].mn[i],T[rc].mn[i]), T[rt].mx[i] = max(T[rt].mx[i],T[rc].mx[i]);
 37     }
 38 }
 39 inline void NewNode(int &rt,Point p) {
 40     rt = Top ? sk[Top--] : ++CntNode;
 41     T[rt].p = p;
 42     T[rt].sz = 1; // --!!! 
 43     T[rt].mn[0] = T[rt].mx[0] = p.x[0];
 44     T[rt].mn[1] = T[rt].mx[1] = p.x[1];
 45 }
 46 int build(int l,int r,int cd) { // cd -- cur dimensions
 47     if (l > r) return 0;
 48     int m = (l + r) >> 1,rt;
 49     Cur = cd; nth_element(P+l, P+m, P+r+1, cmp);
 50     NewNode(rt,P[m]);
 51     lc = build(l, m-1, cd^1);
 52     rc = build(m+1, r, cd^1);
 53     pushup(rt);
 54     return rt;
 55 }
 56 void dfs(int rt,int num) {
 57     if (lc) dfs(lc, num);
 58     P[num+T[lc].sz+1] = T[rt].p, sk[++Top] = rt;
 59     if (rc) dfs(rc, num+T[lc].sz+1);
 60 } 
 61 inline void check(int &rt,int cd) {
 62     if (alpha * T[rt].sz < T[lc].sz || alpha * T[rt].sz < T[rc].sz) {
 63         dfs(rt, 0);
 64         rt = build(1, T[rt].sz, cd);
 65     }
 66 }
 67 void Insert(Point p,int &rt,int cd) {
 68     if (!rt) {
 69         NewNode(rt,p);return ;
 70     }
 71     if (p.x[cd] <= T[rt].p.x[cd]) Insert(p, lc, cd^1);
 72     else Insert(p, rc, cd^1);
 73     pushup(rt);check(rt,cd);
 74 }
 75 inline int dist(Point a,KD_Tree b) {
 76     int dis = 0;
 77     if (a.x[0] < b.mn[0]) dis += b.mn[0] - a.x[0];
 78     if (a.x[0] > b.mx[0]) dis += a.x[0] - b.mx[0];
 79     if (a.x[1] < b.mn[1]) dis += b.mn[1] - a.x[1];
 80     if (a.x[1] > b.mx[1]) dis += a.x[1] - b.mx[1];
 81     return dis;
 82 }
 83 inline int dis(Point a,Point b) {
 84     return abs(a.x[0] - b.x[0]) + abs(a.x[1] - b.x[1]);
 85 }
 86 void query(Point p,int rt) {
 87     Ans = min(Ans,dis(p,T[rt].p)); // -- !!
 88     int dl = lc ? dist(p,T[lc]) : INF;
 89     int dr = rc ? dist(p,T[rc]) : INF;
 90     if (dl < dr) {
 91         if (dl < Ans) query(p,lc);
 92         if (dr < Ans) query(p,rc);
 93     }
 94     else {
 95         if (dr < Ans) query(p,rc);
 96         if (dl < Ans) query(p,lc);
 97     }
 98 }
 99 int main() {
100     int n = read(),m = read();
101     for (int i=1; i<=n; ++i) 
102         P[i].x[0] = read(),P[i].x[1] = read();
103     Root = build(1,n,1);
104     while (m--) {
105         int opt = read(),x = read(),y = read();
106         if (opt == 1) Insert(Point(x,y),Root,1);
107         else {
108             Ans = INF;
109             query(Point(x,y),Root);
110             printf("%d
",Ans);
111         }
112     }
113     return 0;
114 }
View Code
原文地址:https://www.cnblogs.com/mjtcn/p/9295169.html