bzoj 2716 天使玩偶 CDQ分治

来源:互联网 发布:基础建筑学软件 编辑:程序博客网 时间:2024/05/01 05:41

题意,平面内动态加点,每次查询距离目标点曼哈顿距离最短的点,与之的距离

考虑以查询点为原点,其左下角的点与之曼哈顿距离为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[N],sort_by_time[N];int e[N],ans[N],vis[N];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]);}




原创粉丝点击