传送门
题意:
给n个点,每个点出现有先后顺序,求给定位置在给定时间曼哈顿距离最近的点。
题解:CDQ分治
感觉自己CDQ写炸了,常数很大。
首先拆分成4个区域。
考虑j点对i位置的贡献
首先有 tj<ti
1. xj>xi,yj>yi ,此时贡献为 xj+yj−xi−yi 。使 xj+yj 最小。
2. xj>xi,yj<yi ,此时贡献为 xj+yi−xi−yj 。使 xj−yj 最小。
3. xj<xi,yj>yi ,此时贡献为 xi+yj−xj−yi 。使 yj−xj 最小。
4. xj<xi,yj<yi ,此时贡献为 xi+yi−xi−yi 。使 xi+yj 最大。
又是三维偏序,分别用4个树状数组维护即可。
#include
using namespace std;
inline int read()
{
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
int buf[50];
inline void W(int x)
{
if(!x){putchar('0');return;}
if(x<0){putchar('-');x=-x;}
while(x)buf[++buf[0]]=x%10,x/=10;
while(buf[0])putchar(buf[buf[0]--]+'0');
}
const int Maxn=5e5+50;
const int INF=0x3f3f3f3f;
int n,m,lim,ans[4][Maxn],cnt,cnt2,X[Maxn],Y[Maxn],bit[3][Maxn*2];
struct node
{
int type,x,y,id;
}q1[Maxn*2],q2[Maxn*2],tmp[Maxn*2];
inline void insertmax1(int pos,int val){for(;pos<=lim;pos+=(pos&(-pos)))bit[0][pos]=max(bit[0][pos],val);}
inline int querymax1(int pos)
{
int res=-INF;
for(;pos;pos-=(pos&(-pos)))res=max(res,bit[0][pos]);
return res;
}
inline void clearmax1(int pos){for(;pos<=lim;pos+=(pos&(-pos)))bit[0][pos]=-INF;}
inline void insertmin2(int pos,int val){for(;pos<=lim;pos+=(pos&(-pos)))bit[2][pos]=min(bit[2][pos],val);}
inline int querymin2(int pos)
{
int res=INF;
for(;pos;pos-=(pos&(-pos)))res=min(res,bit[2][pos]);
return res;
}
inline void clearmin2(int pos){for(;pos<=lim;pos+=(pos&(-pos)))bit[2][pos]=INF;}
inline void insertmin1(int pos,int val){for(;pos;pos-=(pos&(-pos)))bit[1][pos]=min(bit[1][pos],val);}
inline int querymin1(int pos)
{
int res=INF;
for(;pos<=lim;pos+=(pos&(-pos)))res=min(res,bit[1][pos]);
return res;
}
inline void clearmin1(int pos){for(;pos;pos-=(pos&(-pos)))bit[1][pos]=INF;}
inline void solve(int l,int r)
{
if(l==r)return;
int mid=(l+r)>>1;
solve(l,mid);
solve(mid+1,r);
int head1=l,head2=mid+1,pos=l;
for(int i=l;i<=r;i++)tmp[i]=q1[i];
while(head1<=mid&&head2<=r)
{
if(tmp[head1].x<=tmp[head2].x)
{
if(tmp[head1].type==1)
{
insertmax1(tmp[head1].y,tmp[head1].x+tmp[head1].y);
insertmin1(tmp[head1].y,tmp[head1].y-tmp[head1].x);
}
q1[pos++]=tmp[head1++];
}
else
{
if(tmp[head2].type==2)
{
ans[0][tmp[head2].id]=max(ans[0][tmp[head2].id],querymax1(tmp[head2].y));
ans[1][tmp[head2].id]=min(ans[1][tmp[head2].id],querymin1(tmp[head2].y));
}
q1[pos++]=tmp[head2++];
}
}
while(head1<=mid)
{
if(tmp[head1].type==1)
{
insertmax1(tmp[head1].y,tmp[head1].x+tmp[head1].y);
insertmin1(tmp[head1].y,tmp[head1].y-tmp[head1].x);
}
q1[pos++]=tmp[head1++];
}
while(head2<=r)
{
if(tmp[head2].type==2)
{
ans[0][tmp[head2].id]=max(ans[0][tmp[head2].id],querymax1(tmp[head2].y));
ans[1][tmp[head2].id]=min(ans[1][tmp[head2].id],querymin1(tmp[head2].y));
}
q1[pos++]=tmp[head2++];
}
for(int i=l;i<=mid;i++)if(tmp[i].type==1)clearmax1(tmp[i].y),clearmin1(tmp[i].y);
head1=l,head2=mid+1,pos=l;
for(int i=l;i<=r;i++)tmp[i]=q2[i];
while(head1<=mid&&head2<=r)
{
if(tmp[head1].x>=tmp[head2].x)
{
if(tmp[head1].type==1)
{
insertmin1(tmp[head1].y,tmp[head1].x+tmp[head1].y);
insertmin2(tmp[head1].y,tmp[head1].x-tmp[head1].y);
}
q2[pos++]=tmp[head1++];
}
else
{
if(tmp[head2].type==2)
{
ans[3][tmp[head2].id]=min(ans[3][tmp[head2].id],querymin1(tmp[head2].y));
ans[2][tmp[head2].id]=min(ans[2][tmp[head2].id],querymin2(tmp[head2].y));
}
q2[pos++]=tmp[head2++];
}
}
while(head1<=mid)
{
if(tmp[head1].type==1)
{
insertmin1(tmp[head1].y,tmp[head1].x+tmp[head1].y);
insertmin2(tmp[head1].y,tmp[head1].x-tmp[head1].y);
}
q2[pos++]=tmp[head1++];
}
while(head2<=r)
{
if(tmp[head2].type==2)
{
ans[3][tmp[head2].id]=min(ans[3][tmp[head2].id],querymin1(tmp[head2].y));
ans[2][tmp[head2].id]=min(ans[2][tmp[head2].id],querymin2(tmp[head2].y));
}
q2[pos++]=tmp[head2++];
}
for(int i=l;i<=mid;i++)if(tmp[i].type==1)clearmin1(tmp[i].y),clearmin2(tmp[i].y);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
{
q1[++cnt].x=read();
q1[cnt].y=read();
q1[cnt].type=1;
lim=max(q1[cnt].y,lim);
}
for(int i=1;i<=m;i++)
{
q1[++cnt].type=read();
if(q1[cnt].type!=1)
{
++cnt2;
X[cnt2]=q1[cnt].x=read();
Y[cnt2]=q1[cnt].y=read();
q1[cnt].id=cnt2;
}
else
{
q1[cnt].x=read();
q1[cnt].y=read();
}
lim=max(q1[cnt].y,lim);
}
memcpy(q2,q1,sizeof(q1));
for(int i=1;i<=lim;i++)bit[0][i]=-INF;
memset(bit[1],0x3f,sizeof(bit[1]));
memset(bit[2],0x3f,sizeof(bit[2]));
for(int i=1;i<=cnt2;i++)ans[0][i]=-INF;
memset(ans[1],0x3f,sizeof(ans[1]));
memset(ans[2],0x3f,sizeof(ans[2]));
memset(ans[3],0x3f,sizeof(ans[3]));
solve(1,n+m);
for(int i=1;i<=cnt2;i++)
{
W(min( X[i]+Y[i]-ans[0][i] ,min( X[i]-Y[i]+ans[1][i] ,min( Y[i]-X[i]+ans[2][i] , ans[3][i]-X[i]-Y[i] ))));
putchar('\n');
}
}