luogu

题意

一个平面上有\(n\)个点,\(m\)次操作,每次新增一个点,或者是询问离某个点最近的点的距离。这里的距离是曼哈顿距离。

\(n,m\le3*10^5\)

sol

写一发\(CDQ\)。

只考虑询问点在其他点的右上方的情况,假设询问点是\(A\),那么所求的距离就是\((X_A-X_i)+(Y_A-Y_i)=(X_A+Y_A)-(X_i+Y_i)\)。

所以我们只需要找出满足\(X_i \le X_A,Y_i \le Y_A\)中\(X_i+Y_i\)的最大值就好了。

\(CDQ\)前先按时间戳排序,向上归并时按\(X\)排序。考虑左边对右边的贡献时,按\(Y\)值为下标插入树状数组,然后查询前缀最大值。

对于不在右上方的情况,只要把坐标轴翻转四次就可以了。

然而。
这题卡常。
以下是一些卡常技巧。
>清空树状数组的时候,如果当前位已经是$0$就直接$return$。
预先记录按照时间戳的排序,每次$CDQ$完后直接复制一遍,不需要排序。
删除不必要的点(不会被任何询问考虑到的点)

常数巨大无比。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi()
{
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1e6+5;
struct node{
int tim,opt,x,y;
bool operator < (const node &b) const
{
if (x!=b.x) return x<b.x;
if (y!=b.y) return y<b.y;
return opt<b.opt;
}
}a[N],p[N],q[N];
int n,m,X,Y,c[N],ans[N];
inline void modify(int k,int v){while(k<=Y)c[k]=max(c[k],v),k+=k&-k;}
inline int query(int k){int s=0;while(k)s=max(s,c[k]),k-=k&-k;return s;}
inline void clear(int k){while(k<=Y)if(c[k])c[k]=0,k+=k&-k;else return;}
void CDQ(int l,int r)
{
if (l==r) return;
int mid=l+r>>1;CDQ(l,mid);CDQ(mid+1,r);
int L=l,R=mid+1;
for (int i=l;i<=r;++i)
if (L<=mid&&(R>r||p[L]<p[R]))
{
q[i]=p[L++];
if (q[i].opt==1) modify(q[i].y,q[i].x+q[i].y);
}
else
{
q[i]=p[R++];
if (q[i].opt==2)
{
int tmp=query(q[i].y);
if (tmp) ans[q[i].tim]=min(ans[q[i].tim],q[i].x+q[i].y-tmp);
}
}
for (int i=l;i<=r;++i) p[i]=q[i],clear(p[i].y);
}
void Delete()
{
int xx=0,yy=0;m=0;
for (int i=1;i<=n;++i)
if (p[i].opt==2)
xx=max(xx,p[i].x),yy=max(yy,p[i].y);
for (int i=1;i<=n;++i)
if (p[i].x<=xx&&p[i].y<=yy)
q[++m]=p[i];
for (int i=1;i<=m;++i) p[i]=q[i];
}
int main()
{
n=gi();m=gi();memset(ans,63,sizeof(ans));
for (int i=1;i<=n;++i)
{
a[i]=(node){0,1,gi()+1,gi()+1};
X=max(X,a[i].x);Y=max(Y,a[i].y);
}
for (int i=1;i<=m;++i)
{
a[++n]=(node){i,gi(),gi()+1,gi()+1};
X=max(X,a[n].x);Y=max(Y,a[n].y);
}
++X;++Y;
for (int i=1;i<=n;++i) p[i]=a[i];
Delete();CDQ(1,m);
for (int i=1;i<=n;++i) p[i]=a[i],p[i].x=X-p[i].x;
Delete();CDQ(1,m);
for (int i=1;i<=n;++i) p[i]=a[i],p[i].y=Y-p[i].y;
Delete();CDQ(1,m);
for (int i=1;i<=n;++i) p[i]=a[i],p[i].x=X-p[i].x,p[i].y=Y-p[i].y;
Delete();CDQ(1,m);
for (int i=1;i<=n;++i) if (a[i].opt==2) printf("%d\n",ans[a[i].tim]);
return 0;
}

最新文章

  1. 关于Charles抓取手机访问的Https请求
  2. Java 的静态代理 动态代理(JDK和cglib)
  3. Unity3D——键盘控制移动
  4. HTTP 头部详细解释
  5. grep/awk/sed 或者 并且 否定
  6. linux 下makefile
  7. 关于Verilog 中的for语句的探讨
  8. AJAX最简单的原理以及应用
  9. php获取网页内容方法 小偷程序 采集程序
  10. Leet code —Jump Game
  11. struts2在&amp;lt;s:select&amp;gt;用动态标签
  12. 开源GUI-Microwindows之程序入口分析
  13. Node.js日志框架选型比較:Winston
  14. 剑指前端(前端入门笔记)——Date类型
  15. 【学习】C++多态机制
  16. Navicat Premium 出现2059错误解决办法
  17. 使用新标签兼容低版本IE
  18. DevExpress MemoEdit定位到末尾
  19. 新版谷歌浏览器怎么查找和改变编码格式 IT开发人员谷歌的编码格式
  20. OSPF路由协议(二)

热门文章

  1. Django-JS实现的ajax
  2. h5新特性--- 多媒体元素
  3. 使用AutoIT检测已安装软件,并将结果保存在桌面
  4. 分布式集群Session原理及实现共享
  5. Oracle数据库PLSQL的中文乱码显示全是问号
  6. Spring积累
  7. Luogu-3527 [POI2011]MET-Meteors
  8. Moore majority vote algorithm(摩尔投票算法)
  9. java父类调用被子类重写的方法
  10. QTableWidget 列排序