bzoj4533 [BeiJing2014 WinterCamp] 数据
2016-12-10 22:42
218 查看
【题意】
n个点,m个操作,共3种:
1.加点
2.查询点集到定点曼哈顿距离最小值
3.查询点集到定点曼哈顿距离最大值
【数据范围】
n<=100000,m<=100000
【思路】
kd-tree模板题。
求曼哈顿距离最小值:
估价函数为该点与边框矩形的最小距离,优先查询估价小的子树,若子树估价>=ans则忽略此子树。
求曼哈顿距离最大值:
估价函数为该点与边框4个顶点的最大距离(即该点与边框矩形的最大距离),优先查询估价大的子树,若子树估价<=ans则忽略此子树。
【时间复杂度】
O((n+m)sqrt(n+m))
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 200010
#define inf 2147483647
using namespace std;
struct aa{int d[2];}a
;
struct tt{int l, r, d[2], mx[2], mn[2];}t
;
int n, B, m, l, D, x, y, ans, temp;
inline int read(){
int x=0, f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
bool operator<(aa a, aa b){return a.d[D]<b.d[D];}
void update(int i){
for(int j=0; j<=1; j++){
t[i].mx[j]=t[i].mn[j]=t[i].d[j];
if(t[i].l){
t[i].mx[j]=max(t[i].mx[j], t[t[i].l].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].l].mn[j]);
}
if(t[i].r){
t[i].mx[j]=max(t[i].mx[j], t[t[i].r].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].r].mn[j]);
}
}
}
void kd_maketree(int L, int R, int now){
t[l].l=t[l].r=0; D=now;
int mid=(L+R)>>1;
nth_element(a+L, a+mid, a+R+1);
t[l].d[0]=a[mid].d[0]; t[l].d[1]=a[mid].d[1];
int l1=l;
if(L<mid){l++; t[l1].l=l; kd_maketree(L, mid-1, now^1);}
if(mid<R){l++; t[l1].r=l; kd_maketree(mid+1, R, now^1);}
update(l1);
}
void kd_ins(int i, int x, int y, int now, int fa, int p){
if(!i){
l++; t[l].l=t[l].r=0;
t[l].d[0]=x; t[l].d[1]=y; update(l);
if(!p)t[fa].l=l; else t[fa].r=l;
return;
}
if(t[i].d[0]==x&&t[i].d[1]==y)return;
if(!now){
if(x<=t[i].d[0])kd_ins(t[i].l, x, y, now^1, i, 0);
else kd_ins(t[i].r, x, y, now^1, i, 1);
}else{
if(y<=t[i].d[1])kd_ins(t[i].l, x, y, now^1, i, 0);
else kd_ins(t[i].r, x, y, now^1, i, 1);
}
update(i);
}
int getmn(int i, int x, int y){
return max(t[i].mn[0]-x, 0)+max(x-t[i].mx[0], 0)+max(t[i].mn[1]-y, 0)+max(y-t[i].mx[1], 0);
}
int getmx(int i, int x, int y){
return max(abs(x-t[i].mn[0]), abs(x-t[i].mx[0]))+max(abs(y-t[i].mn[1]), abs(y-t[i].mx[1]));
}
void cmn(int i, int x, int y){
if(!i)return;
ans=min(ans, abs(t[i].d[0]-x)+abs(t[i].d[1]-y));
int h1=t[i].l?getmn(t[i].l, x, y):inf;
int h2=t[i].r?getmn(t[i].r, x, y):inf;
if(h1<=h2){
if(ans>h1)cmn(t[i].l, x, y);
if(ans>h2)cmn(t[i].r, x, y);
}else{
if(ans>h2)cmn(t[i].r, x, y);
if(ans>h1)cmn(t[i].l, x, y);
}
}
void cmx(int i, int x, int y){
if(!i)return;
ans=max(ans, abs(t[i].d[0]-x)+abs(t[i].d[1]-y));
int h1=t[i].l?getmx(t[i].l, x, y):0;
int h2=t[i].r?getmx(t[i].r, x, y):0;
if(h1>=h2){
if(ans<h1)cmx(t[i].l, x, y);
if(ans<h2)cmx(t[i].r, x, y);
}else{
if(ans<h2)cmx(t[i].r, x, y);
if(ans<h1)cmx(t[i].l, x, y);
}
}
int main(){
n=read();
for(int i=1; i<=n; i++){a[i].d[0]=read(); a[i].d[1]=read();}
l=1; kd_maketree(1, n, 0);
B=n+10000;
m=read();
for(int i=1; i<=m; i++){
temp=read(); x=read(); y=read();
if(!temp){
a[++n].d[0]=x; a
.d[1]=y;
kd_ins(1, a
.d[0], a
.d[1], 0, 0, 0);
if(n==B){
l=1; kd_maketree(1, n, 0);
B+=10000;
}
}
if(temp==1){ans=inf; cmn(1, x, y); printf("%d\n", ans);}
if(temp==2){ans=0; cmx(1, x, y); printf("%d\n", ans);}
}
return 0;
}
n个点,m个操作,共3种:
1.加点
2.查询点集到定点曼哈顿距离最小值
3.查询点集到定点曼哈顿距离最大值
【数据范围】
n<=100000,m<=100000
【思路】
kd-tree模板题。
求曼哈顿距离最小值:
估价函数为该点与边框矩形的最小距离,优先查询估价小的子树,若子树估价>=ans则忽略此子树。
求曼哈顿距离最大值:
估价函数为该点与边框4个顶点的最大距离(即该点与边框矩形的最大距离),优先查询估价大的子树,若子树估价<=ans则忽略此子树。
【时间复杂度】
O((n+m)sqrt(n+m))
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 200010
#define inf 2147483647
using namespace std;
struct aa{int d[2];}a
;
struct tt{int l, r, d[2], mx[2], mn[2];}t
;
int n, B, m, l, D, x, y, ans, temp;
inline int read(){
int x=0, f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
bool operator<(aa a, aa b){return a.d[D]<b.d[D];}
void update(int i){
for(int j=0; j<=1; j++){
t[i].mx[j]=t[i].mn[j]=t[i].d[j];
if(t[i].l){
t[i].mx[j]=max(t[i].mx[j], t[t[i].l].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].l].mn[j]);
}
if(t[i].r){
t[i].mx[j]=max(t[i].mx[j], t[t[i].r].mx[j]);
t[i].mn[j]=min(t[i].mn[j], t[t[i].r].mn[j]);
}
}
}
void kd_maketree(int L, int R, int now){
t[l].l=t[l].r=0; D=now;
int mid=(L+R)>>1;
nth_element(a+L, a+mid, a+R+1);
t[l].d[0]=a[mid].d[0]; t[l].d[1]=a[mid].d[1];
int l1=l;
if(L<mid){l++; t[l1].l=l; kd_maketree(L, mid-1, now^1);}
if(mid<R){l++; t[l1].r=l; kd_maketree(mid+1, R, now^1);}
update(l1);
}
void kd_ins(int i, int x, int y, int now, int fa, int p){
if(!i){
l++; t[l].l=t[l].r=0;
t[l].d[0]=x; t[l].d[1]=y; update(l);
if(!p)t[fa].l=l; else t[fa].r=l;
return;
}
if(t[i].d[0]==x&&t[i].d[1]==y)return;
if(!now){
if(x<=t[i].d[0])kd_ins(t[i].l, x, y, now^1, i, 0);
else kd_ins(t[i].r, x, y, now^1, i, 1);
}else{
if(y<=t[i].d[1])kd_ins(t[i].l, x, y, now^1, i, 0);
else kd_ins(t[i].r, x, y, now^1, i, 1);
}
update(i);
}
int getmn(int i, int x, int y){
return max(t[i].mn[0]-x, 0)+max(x-t[i].mx[0], 0)+max(t[i].mn[1]-y, 0)+max(y-t[i].mx[1], 0);
}
int getmx(int i, int x, int y){
return max(abs(x-t[i].mn[0]), abs(x-t[i].mx[0]))+max(abs(y-t[i].mn[1]), abs(y-t[i].mx[1]));
}
void cmn(int i, int x, int y){
if(!i)return;
ans=min(ans, abs(t[i].d[0]-x)+abs(t[i].d[1]-y));
int h1=t[i].l?getmn(t[i].l, x, y):inf;
int h2=t[i].r?getmn(t[i].r, x, y):inf;
if(h1<=h2){
if(ans>h1)cmn(t[i].l, x, y);
if(ans>h2)cmn(t[i].r, x, y);
}else{
if(ans>h2)cmn(t[i].r, x, y);
if(ans>h1)cmn(t[i].l, x, y);
}
}
void cmx(int i, int x, int y){
if(!i)return;
ans=max(ans, abs(t[i].d[0]-x)+abs(t[i].d[1]-y));
int h1=t[i].l?getmx(t[i].l, x, y):0;
int h2=t[i].r?getmx(t[i].r, x, y):0;
if(h1>=h2){
if(ans<h1)cmx(t[i].l, x, y);
if(ans<h2)cmx(t[i].r, x, y);
}else{
if(ans<h2)cmx(t[i].r, x, y);
if(ans<h1)cmx(t[i].l, x, y);
}
}
int main(){
n=read();
for(int i=1; i<=n; i++){a[i].d[0]=read(); a[i].d[1]=read();}
l=1; kd_maketree(1, n, 0);
B=n+10000;
m=read();
for(int i=1; i<=m; i++){
temp=read(); x=read(); y=read();
if(!temp){
a[++n].d[0]=x; a
.d[1]=y;
kd_ins(1, a
.d[0], a
.d[1], 0, 0, 0);
if(n==B){
l=1; kd_maketree(1, n, 0);
B+=10000;
}
}
if(temp==1){ans=inf; cmn(1, x, y); printf("%d\n", ans);}
if(temp==2){ans=0; cmx(1, x, y); printf("%d\n", ans);}
}
return 0;
}
相关文章推荐
- cross apply 和 outer apply
- 空气质量指数美国标准和中国标准差别
- Java源码侦探-Integer方法解读
- JUnit测试框架使用介绍
- javascript是html5和所有现代浏览器中的默认脚本语言
- 解决MySql 数据库 提示:1045 access denied for user 'root'@'localhost' using password yes
- Python 对不均衡数据进行Over sample(重抽样)
- mount命令的用法,以及技巧光盘镜像文件、移动硬盘及U盘的方法
- java学习(集合类)
- 【软件周刊】Android 7.1.1 正式版发布:提升续航,支持压感;WordPress 4.7 正式版 “Vaughan” 带来全新默认主题
- 前端学HTTP之报文起始行
- Python 爬虫知识点
- java学习(基础知识,适合学过c/c++的)
- Dom选择器及操作文本内容
- 希尔排序
- Shell变量
- 机器学习第二课:无约束优化问题(局部极小值的几种解法)(梯度下降法与拟牛顿法)
- python 自动化之pywinauto 安装
- hdoj-【2527 Safe Or Unsafe】
- Activity之间传递数据的方法总结