您的位置:首页 > 其它

bzoj 2716 天使玩偶 CDQ分治

2017-07-01 11:01 197 查看
题意,平面内动态加点,每次查询距离目标点曼哈顿距离最短的点,与之的距离

考虑以查询点为原点,其左下角的点与之曼哈顿距离为dis=(x-x')+(y-y')=(x+y)-(x'+y')

因此,我们考虑求(x'+y')最大值

CDQ分治来解决此题

首先考虑将所有点,无论是目标点还是插入的点,按X坐标排序

再对于时间进行分治

对于分治后得到的两段,分别在内部再次按X坐标排序,

之后创建两个指针,分别在,左半块和右半块滑动,并且始终使,右半块中指针所指的查询的点的时间,晚于左半块中插入点的时间

然后动态在树状数组中加入右半块中要插入的点

最后查询X+Y最大值

最后计算一下,直接更改点坐标,是右上等情况也满足左下的情况

共调用cdq 3次

代码如下

#include<bits/stdc++.h>
using namespace std;
const int N=1001000;
struct node{
bool is_ques;
int x,y,id;
}P
,sort_by_time
;
int e
,ans
,vis
;
int n,m,cnt=0;
inline void R(int &x)
{
x=0;
char c=getchar();
int p=1;
while(c<'0'||c>'9')
{
if(c=='-')
p=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<1)+(x<<3)+(c^'0');
c=getchar();
}
x*=p;
}
bool comp(node a,node b){return a.x<b.x;}
int lowbit(int x)
{return x&(-x);}
void add(int pos,int val)
{
if(!pos)return;
while(pos<N)
{
e[pos]=max(e[pos],val);
pos+=lowbit(pos);
}
}
int query(int pos)
{
int res=-1;
while(pos>0)
{
res=max(res,e[pos]);
pos-=lowbit(pos);
}
return res;
}
void release(int pos)
{
if(!pos)return;
while(pos<N)e[pos]=-1,pos+=lowbit(pos);
}
void cdq(int l,int r)
{
if(l==r)return;
int mid=l+r>>1;
int c1=l,c2=mid+1;
for(int i=l;i<=r;i++)
{
if(P[i].id<=mid)
sort_by_time[c1++]=P[i];
else sort_by_time[c2++]=P[i];
}
for(int i=l;i<=r;i++)P[i]=sort_by_time[i];
int j=l,temp=0;
for(int i=mid+1;i<=r;i++)
{
if(P[i].is_ques)
{
while(P[j].x<=P[i].x&&j<=mid)
{
if(!P[j].is_ques)add(P[j].y,P[j].x+P[j].y);
vis[++temp]=P[j].y;
j++;
}
int maxx=query(P[i].y);
if(maxx!=-1)
ans[P[i].id]=min(ans[P[i].id],P[i].x+P[i].y-maxx);
}
}
for(int i=1;i<=temp;i++)release(vis[i]);
cdq(l,mid);
cdq(mid+1,r);
}
int main()
{
//	freopen("in.in","r",stdin);
R(n);R(m);
int t,x,y,Max=-1;
for(int i=1;i<=n;i++)
{
R(x);R(y);
cnt++;
P[cnt].id=cnt;
P[cnt].x=x;
P[cnt].y=y;
Max=max(Max,x);
Max=max(Max,y);
P[cnt].is_ques=0;
}
for(int i=1;i<=m;i++)
{
R(t);R(x);R(y);
Max=max(Max,x);
Max=max(Max,y);
cnt++;
P[cnt].id=cnt;
P[cnt].x=x;
P[cnt].y=y;
if(t==1)P[cnt].is_ques=0;
else P[cnt].is_ques=1;
}
//	cout<<Max<<endl;
sort(P+1,P+cnt+1,comp);
memset(e,-1,sizeof(e));
memset(ans,127,sizeof(ans));
cdq(1,cnt);

for(int i=1;i<=cnt;i++)P[i].y=Max-P[i].y+1;
sort(P+1,P+cnt+1,comp);cdq(1,cnt);

for(int i=1;i<=cnt;i++)P[i].x=Max-P[i].x+1;
sort(P+1,P+cnt+1,comp);cdq(1,cnt);

for(int i=1;i<=cnt;i++)P[i].y=Max-P[i].y+1;
sort(P+1,P+cnt+1,comp);cdq(1,cnt);

for(int i=n+1;i<=cnt;i++)
if(ans[i]<1e9)printf("%d\n",ans[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cdq bzoj 2716