样例好良心。
写CDQ写腻了,这道题还是学一学KD-Tree吧。
KD-Tree,可以认为是在K维空间上二分答案。
将二分得到的顺序建树。
这样的结构很难支持修改,所以暴力插入。
应用替罪羊的想法,不优秀就暴力重建。
时间复杂度玄学。(维护矩形曼哈顿距离)
非常开心地AC
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 typedef long long lnt; 5 const int D=2; 6 const int maxn=1000000; 7 const double alpha=0.75; 8 int here; 9 struct KD_pnt{ 10 int v[D]; 11 bool friend operator < (KD_pnt x,KD_pnt y) 12 { 13 return x.v[here]<y.v[here]; 14 } 15 }p[maxn]; 16 struct KD_trnt{ 17 KD_pnt val; 18 KD_pnt mx; 19 KD_pnt mn; 20 int ls; 21 int rs; 22 int wgt; 23 }kt[maxn],stdkt; 24 int n,m; 25 int ans; 26 int top; 27 int siz; 28 int root; 29 int bin[maxn]; 30 inline int read(void) 31 { 32 int anss=0,f=1; 33 char ch=getchar(); 34 while(ch<‘0‘||ch>‘9‘) 35 { 36 if(ch==‘-‘) 37 f=-f; 38 ch=getchar(); 39 } 40 while(ch>=‘0‘&&ch<=‘9‘) 41 { 42 anss=anss*10+ch-‘0‘; 43 ch=getchar(); 44 } 45 return anss*f; 46 } 47 int newp(void) 48 { 49 if(top) 50 return bin[top--]; 51 return ++siz; 52 } 53 void Trash(int spc) 54 { 55 bin[++top]=spc; 56 return ; 57 } 58 void apply(int &spc) 59 { 60 spc=newp(); 61 kt[spc]=stdkt; 62 return ; 63 } 64 int Dist(KD_pnt a,KD_pnt b) 65 { 66 int ans=0; 67 for(int i=0;i<D;i++) 68 ans+=std::abs(a.v[i]-b.v[i]); 69 return ans; 70 } 71 int assess(KD_pnt a,int spc) 72 { 73 int ans=0; 74 for(int i=0;i<D;i++) 75 ans+=std::max(0,a.v[i]-kt[spc].mx.v[i])+std::max(0,kt[spc].mn.v[i]-a.v[i]); 76 return ans; 77 } 78 void pushup(int spc) 79 { 80 kt[spc].mx=kt[spc].mn=kt[spc].val; 81 if(kt[spc].ls) 82 { 83 kt[spc].mx.v[0]=std::max(kt[spc].mx.v[0],kt[kt[spc].ls].mx.v[0]); 84 kt[spc].mn.v[0]=std::min(kt[spc].mn.v[0],kt[kt[spc].ls].mn.v[0]); 85 kt[spc].mx.v[1]=std::max(kt[spc].mx.v[1],kt[kt[spc].ls].mx.v[1]); 86 kt[spc].mn.v[1]=std::min(kt[spc].mn.v[1],kt[kt[spc].ls].mn.v[1]); 87 } 88 if(kt[spc].rs) 89 { 90 kt[spc].mx.v[0]=std::max(kt[spc].mx.v[0],kt[kt[spc].rs].mx.v[0]); 91 kt[spc].mn.v[0]=std::min(kt[spc].mn.v[0],kt[kt[spc].rs].mn.v[0]); 92 kt[spc].mx.v[1]=std::max(kt[spc].mx.v[1],kt[kt[spc].rs].mx.v[1]); 93 kt[spc].mn.v[1]=std::min(kt[spc].mn.v[1],kt[kt[spc].rs].mn.v[1]); 94 } 95 kt[spc].wgt=1+kt[kt[spc].ls].wgt+kt[kt[spc].rs].wgt; 96 return ; 97 } 98 void build(int l,int r,int dim,int &spc) 99 { 100 if(l>r) 101 { 102 spc=0; 103 return ; 104 } 105 apply(spc); 106 here=dim; 107 int mid=(l+r)>>1; 108 std::nth_element(p+l,p+mid,p+r+1); 109 kt[spc].val=p[mid]; 110 build(l,mid-1,dim^1,kt[spc].ls); 111 build(mid+1,r,dim^1,kt[spc].rs); 112 pushup(spc); 113 return ; 114 } 115 void Destory(int spc,int sta) 116 { 117 if(kt[spc].ls) 118 Destory(kt[spc].ls,sta); 119 p[sta+kt[kt[spc].ls].wgt+1]=kt[spc].val; 120 Trash(spc); 121 if(kt[spc].rs) 122 Destory(kt[spc].rs,sta+kt[kt[spc].ls].wgt+1); 123 return ; 124 } 125 bool imbalance(int root) 126 { 127 return ((double)(std::max(kt[kt[root].ls].wgt,kt[kt[root].rs].wgt))>alpha*(double)(kt[root].wgt)); 128 } 129 void rebuild(int &spc,int dim) 130 { 131 Destory(spc,0); 132 build(1,kt[spc].wgt,dim,spc); 133 return ; 134 } 135 void Insert(int &spc,KD_pnt x,int dim) 136 { 137 if(!spc) 138 { 139 apply(spc); 140 kt[spc].val=x; 141 pushup(spc); 142 return ; 143 } 144 if(kt[spc].val.v[dim]<x.v[dim]) 145 Insert(kt[spc].rs,x,dim^1); 146 else 147 Insert(kt[spc].ls,x,dim^1); 148 pushup(spc); 149 if(imbalance(spc)) 150 rebuild(spc,dim); 151 return ; 152 } 153 void Query(int spc,KD_pnt x) 154 { 155 if(!spc) 156 return ; 157 ans=std::min(ans,Dist(x,kt[spc].val)); 158 int disls,disrs; 159 if(kt[spc].ls) 160 disls=assess(x,kt[spc].ls); 161 else 162 disls=0x7f7f7f7f; 163 if(kt[spc].rs) 164 disrs=assess(x,kt[spc].rs); 165 else 166 disrs=0x7f7f7f7f; 167 if(disls<disrs) 168 { 169 if(disls<ans) 170 Query(kt[spc].ls,x); 171 if(disrs<ans) 172 Query(kt[spc].rs,x); 173 }else{ 174 if(disrs<ans) 175 Query(kt[spc].rs,x); 176 if(disls<ans) 177 Query(kt[spc].ls,x); 178 } 179 return ; 180 } 181 int main() 182 { 183 n=read(); 184 m=read(); 185 for(int i=1;i<=n;i++) 186 p[i].v[0]=read(),p[i].v[1]=read();; 187 build(1,n,0,root); 188 while(m--) 189 { 190 int cmd; 191 KD_pnt x; 192 ans=0x7f7f7f7f; 193 cmd=read(); 194 x.v[0]=read(); 195 x.v[1]=read(); 196 if(cmd==1) 197 Insert(root,x,0); 198 else{ 199 Query(root,x); 200 printf("%d\n",ans); 201 } 202 } 203 return 0; 204 }
BZOJ2716: [Violet 3]天使玩偶(KD-Tree)
原文:https://www.cnblogs.com/blog-Dr-J/p/10115995.html