您的位置:首页 > 其它

1941: [Sdoi2010]Hide and Seek|动态加点线段树

2016-03-11 15:42 435 查看
传统的K-Dtree姿势http://blog.csdn.net/ws_yzy/article/details/50855522

对计算曼哈顿距离分四种情况讨论,枚举每一个点,维护它的左下,左上,右下,右上的点,在相同区域的点的计算曼哈顿距离的符号是相同的

先用左下方的点更新每一个点,对于点(x,y),此时线段树中存的是−x−y,维护最大值和最小值

从左到右枚举每一个点(x,y),询问线段树中区间[0,y]中的最大值和最小值来更新到这个点的距离的最值,然后在将该点插入到线段树中

其他区域也同理

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#define N 4000022
#define M 500050
using namespace std;
int sc()
{
int i=0,f=1; char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i*f;
}
struct W{int x,y;}a[M];
int mn
,mx
,ll
,lr
,cnt;
int ans1[M],ans2[M];
int n,MX,root,ans=1e9;
bool cmp(W a,W b)
{
return a.x<b.x;
}
void push_up(int x)
{
mn[x]=min(mn[ll[x]],mn[lr[x]]);
mx[x]=max(mx[ll[x]],mx[lr[x]]);
}
void insert(int &x,int l,int r,int p,int v)
{
if(l==r)
{
if(x)
mn[x]=min(mn[x],v),
mx[x]=max(mx[x],v);
else x=++cnt,mn[x]=mx[x]=v;
return;
}
if(!x)x=++cnt;
int mid=l+r>>1;
if(p<=mid)insert(ll[x],l,mid,p,v);
else insert(lr[x],mid+1,r,p,v);
push_up(x);
}
int query_mx(int x,int L,int R,int l,int r)
{
if(!x)return -1e9;
if(L==l&&R==r)return mx[x];
int mid=L+R>>1;
if(r<=mid)return query_mx(ll[x],L,mid,l,r);
else if(l>mid)return query_mx(lr[x],mid+1,R,l,r);
else return max(query_mx(ll[x],L,mid,l,mid),query_mx(lr[x],mid+1,R,mid+1,r));
}
int query_mn(int x,int L,int R,int l,int r)
{
if(!x)return 1e9;
if(L==l&&R==r)return mn[x];
int mid=L+R>>1;
if(r<=mid)return query_mn(ll[x],L,mid,l,r);
else if(l>mid)return query_mn(lr[x],mid+1,R,l,r);
else return min(query_mn(ll[x],L,mid,l,mid),query_mn(lr[x],mid+1,R,mid+1,r));
}
int main()
{
mn[0]=1e9,mx[0]=-1e9;
n=sc();
for(int i=1;i<=n;i++)
ans1[i]=-1e9,ans2[i]=1e9,
a[i].x=sc(),a[i].y=sc(),
MX=max(MX,max(a[i].x,a[i].y));
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
ans1[i]=max(ans1[i],a[i].x+a[i].y+query_mx(root,0,MX,0,a[i].y));
ans2[i]=min(ans2[i],a[i].x+a[i].y+query_mn(root,0,MX,0,a[i].y));
insert(root,0,MX,a[i].y,-a[i].x-a[i].y);
}
for(int i=1;i<=cnt;i++)
ll[i]=lr[i]=0;
root=cnt=0;
for(int i=1;i<=n;i++)
{
ans1[i]=max(ans1[i],a[i].x-a[i].y+query_mx(root,0,MX,a[i].y,MX));
ans2[i]=min(ans2[i],a[i].x-a[i].y+query_mn(root,0,MX,a[i].y,MX));
insert(root,0,MX,a[i].y,-a[i].x+a[i].y);
}
for(int i=1;i<=cnt;i++)
ll[i]=lr[i]=0;
root=cnt=0;
for(int i=n;i>=1;i--)
{
ans1[i]=max(ans1[i],-a[i].x+a[i].y+query_mx(root,0,MX,0,a[i].y));
ans2[i]=min(ans2[i],-a[i].x+a[i].y+query_mn(root,0,MX,0,a[i].y));
insert(root,0,MX,a[i].y,a[i].x-a[i].y);
}
for(int i=1;i<=cnt;i++)
ll[i]=lr[i]=0;
root=cnt=0;
for(int i=n;i>=1;i--)
{
ans1[i]=max(ans1[i],-a[i].x-a[i].y+query_mx(root,0,MX,a[i].y,MX));
ans2[i]=min(ans2[i],-a[i].x-a[i].y+query_mn(root,0,MX,a[i].y,MX));
insert(root,0,MX,a[i].y,a[i].x+a[i].y);
}
for(int i=1;i<=n;i++)
ans=min(ans,ans1[i]-ans2[i]);
cout<<ans;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树