LINK:数据
这是一个我写过的最标准的板子。
重构什么的写的非常的标准 常数应该也算很小的。
不过虽然过了题 我也不知道代码是否真的无误 反正我已经眼查三遍了...
重构:建议先插入 插入过程中找到第一个不平衡的点再重构。
最小距离查询剪枝:当前坐标为mn和mx中间的时候显然 最小距离可能为0 否则 为他们其中之一和当前坐标的差。
最大距离查询剪枝:当前坐标和mn以及mx的最大距离差。
const int MAXN=500010,K=2;
const db alpha=0.75;
int n,root,top,D,Q,cnt,ans;
struct wy
{
int d[K];
int mn[K],mx[K];
int sz,l,r;
}t[MAXN];
int q[MAXN];
inline int cmp(int a,int b){return t[a].d[D]<t[b].d[D];}
inline void update(int x)
{
sz(x)=sz(l(x))+sz(r(x))+1;
for(int i=0;i<K;++i)
{
if(l(x))t[x].mx[i]=max(t[x].mx[i],t[l(x)].mx[i]),t[x].mn[i]=min(t[x].mn[i],t[l(x)].mn[i]);
if(r(x))t[x].mx[i]=max(t[x].mx[i],t[r(x)].mx[i]),t[x].mn[i]=min(t[x].mn[i],t[r(x)].mn[i]);
}
}
inline int build(int l,int r,int k)
{
if(l>r)return 0;
int mid=(l+r)>>1;D=k;
nth_element(q+l,q+mid,q+1+r,cmp);
int x=q[mid];
for(int i=0;i<K;++i)t[x].mx[i]=t[x].mn[i]=t[x].d[i];
l(x)=build(l,mid-1,(k+1)%K);
r(x)=build(mid+1,r,(k+1)%K);
update(x);return x;
}
inline void erase(int x)
{
if(!x)return;q[++top]=x;
erase(l(x));erase(r(x));
}
inline void rebuild(int &x,int k)
{
top=0;erase(x);
x=build(1,top,k);
}
inline void insert(int &p,int k,int flag)
{
if(!p)
{
p=++cnt;sz(p)=1;
for(int i=0;i<K;++i)t[p].mx[i]=t[p].mn[i]=t[p].d[i]=q[i];
return;
}
int mark=0;
if(q[k]<t[p].d[k])
{
if((sz(l(p))+1)>=alpha*(sz(p)+1))mark=1;
insert(l(p),(k+1)%K,flag|mark);
}
else
{
if((sz(r(p)+1)>=alpha*(sz(p)+1)))mark=1;
insert(r(p),(k+1)%K,flag|mark);
}
if(!flag&&mark)rebuild(p,k);
update(p);
}
inline int dis(int x)
{
int cnt=0;
rep(0,K-1,i)cnt+=abs(t[x].d[i]-q[i]);
return cnt;
}
inline int dismin(int x)//查当前离节点最近的距离
{
int cnt=0;
rep(0,K-1,i)if(q[i]<t[x].mn[i])cnt+=t[x].mn[i]-q[i];
else if(q[i]>t[x].mx[i])cnt+=q[i]-t[x].mx[i];
return cnt;
}
inline void ask_min(int x)
{
ans=min(ans,dis(x));
int L=dismin(l(x));
int R=dismin(r(x));
if(L<R)
{
if(L<ans&&l(x))ask_min(l(x));
if(R<ans&&r(x))ask_min(r(x));
}
else
{
if(R<ans&&r(x))ask_min(r(x));
if(L<ans&&l(x))ask_min(l(x));
}
}
inline int dismax(int x)
{
int cnt=0;
rep(0,K-1,i)cnt+=max(abs(q[i]-t[x].mn[i]),abs(q[i]-t[x].mx[i]));
return cnt;
}
inline void ask_max(int x)
{
ans=max(ans,dis(x));
int L=dismax(l(x));
int R=dismax(r(x));
if(L>R)
{
if(L>ans&&l(x))ask_max(l(x));
if(R>ans&&r(x))ask_max(r(x));
}
else
{
if(R>ans&&r(x))ask_max(r(x));
if(L>ans&&l(x))ask_max(l(x));
}
}
int main()
{
freopen("1.in","r",stdin);
get(n);cnt=n;
rep(1,n,i)
{
int get(x);int get(y);
t[i].d[0]=x;t[i].d[1]=y;
q[i]=i;
}
root=build(1,n,0);
get(Q);
rep(1,Q,i)
{
int op;
get(op);get(q[0]);get(q[1]);
if(op==0)insert(root,0,0);
if(op==1)
{
ans=INF;
ask_min(root);
put(ans);
}
if(op==2)
{
ans=-INF;
ask_max(root);
put(ans);
}
}
return 0;
}