6
19
2016
0

[BZOJ2716] [Violet 3]天使玩偶

这个题和BZOJ2648基本是一样的

理论上直接交就能过

但是在学校的OJ上被卡到95分了很悲伤

算了就放这个BZOJ可以过但是被卡常的版本

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
 
const register int N=500005,INF=2100000000;
 
static int n,m,Sort_Tag,root,ans=INF;
 
struct KDTree{
int l,r,d[2],mn[2],mx[2];
KDTree(){}
KDTree(register int x,register int y){mn[0]=mx[0]=d[0]=x;mn[1]=mx[1]=d[1]=y;l=r=0;}
inline friend bool operator<(register KDTree A,register KDTree B){return A.d[Sort_Tag]<B.d[Sort_Tag];}
}tree[N<<2],Temp;
 
inline int Max(register int x,register int y){return x<y?y:x;}
inline int Min(register int x,register int y){return x<y?x:y;}
inline int Abs(register int x){return x>0?x:-x;}
inline int Dist(register KDTree A,register KDTree B){return Abs(A.d[0]-B.d[0])+Abs(A.d[1]-B.d[1]);}
 
inline void Pushup(register int rt){
if(tree[rt].l){
    tree[rt].mn[0]=Min(tree[rt].mn[0],tree[tree[rt].l].mn[0]);
    tree[rt].mn[1]=Min(tree[rt].mn[1],tree[tree[rt].l].mn[1]);
    tree[rt].mx[0]=Max(tree[rt].mx[0],tree[tree[rt].l].mx[0]);
    tree[rt].mx[1]=Max(tree[rt].mx[1],tree[tree[rt].l].mx[1]);
}
if(tree[rt].r){
    tree[rt].mn[0]=Min(tree[rt].mn[0],tree[tree[rt].r].mn[0]);
    tree[rt].mn[1]=Min(tree[rt].mn[1],tree[tree[rt].r].mn[1]);
    tree[rt].mx[0]=Max(tree[rt].mx[0],tree[tree[rt].r].mx[0]);
    tree[rt].mx[1]=Max(tree[rt].mx[1],tree[tree[rt].r].mx[1]);
}
}
 
inline int Build(register int l,register int r,register int D){
Sort_Tag=D;
register int mid=l+r>>1;
nth_element(tree+l,tree+mid,tree+r+1);
tree[mid].mn[0]=tree[mid].mx[0]=tree[mid].d[0];
tree[mid].mn[1]=tree[mid].mx[1]=tree[mid].d[1];
if(l<mid)tree[mid].l=Build(l,mid-1,!D);
if(r>mid)tree[mid].r=Build(mid+1,r,!D);
Pushup(mid);
return mid;
}
 
inline void _Insert(register int rt,register int D){
if(Temp.d[D]>=tree[rt].d[D]){
    if(tree[rt].r)_Insert(tree[rt].r,!D);
    else {tree[rt].r=++n;tree[n]=Temp;}
}
else {
    if(tree[rt].l)_Insert(tree[rt].l,!D);
    else {tree[rt].l=++n;tree[n]=Temp;}
}
Pushup(rt);
}
 
inline void Insert(register int x,register int y){
Temp=KDTree(x,y);
_Insert(root,0);
}
 
inline int MxDist(register int rt,register int x,register int y){
return Max(tree[rt].mn[0]-x,0)+Max(tree[rt].mn[1]-y,0)+Max(x-tree[rt].mx[0],0)+Max(y-tree[rt].mx[1],0);
}
 
inline void _Query(register int rt){
register int Dl=INF,Dr=INF,Dm=Dist(tree[rt],Temp);
ans=Min(ans,Dm);
if(tree[rt].l)Dl=MxDist(tree[rt].l,Temp.d[0],Temp.d[1]);
if(tree[rt].r)Dr=MxDist(tree[rt].r,Temp.d[0],Temp.d[1]);
if(Dl<Dr){
    if(Dl<ans)_Query(tree[rt].l);
    if(Dr<ans)_Query(tree[rt].r);
}
else {
    if(Dr<ans)_Query(tree[rt].r);
    if(Dl<ans)_Query(tree[rt].l);
}
}
 
inline int Query(register int x,register int y){
Temp=KDTree(x,y);ans=INF;
_Query(root);
return ans;
}
 
inline void Read(register int &x){
register char ch;
while((ch=getchar())<'0' || ch>'9');
x=ch-'0';
while((ch=getchar())>='0' && ch<='9')x=x*10+ch-'0';
}
 
int main(){
freopen("2716.in","r",stdin);
freopen("2716.out","w",stdout);
Read(n);Read(m);
for(register int i=1;i<=n;i++)Read(tree[i].d[0]),Read(tree[i].d[1]);
root=Build(1,n,0);
for(register int i=1;i<=m;i++){
    register int opt,x,y;
    Read(opt);Read(x);Read(y);
    if(opt==1)Insert(x,y);
    if(opt==2)printf("%d\n",Query(x,y));
}
return 0;
}

lzz(C_SUNSHINE)的卡常版本,比我快的不知道到哪里去了(还是不放比较好……)(就是查询时做了一些神奇的优化)

Category: BZOJ | Tags: OI bzoj | Read Count: 2657

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com