bzoj2648SJY摆棋子

bzoj2648SJY摆棋子

bzoj2716[Violet 3]天使玩偶

题意:

棋盘上有n个棋子,现在有m个操作,一种是加棋子,一种是查询离某个点最近的棋子。n,m≤500000。

题解:

先将已有的棋子建kd树,然后加棋子就直接向kd树插入节点。因为本题数据弱,所以直接插节点不会T,如果是一些数据比较强的题目,需要在插入一定量节点后重构整棵树。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define maxn 500010
 6 #define INF 0x3fffffff
 7 using namespace std;
 8
 9 inline int read(){
10     char ch=getchar(); int f=1,x=0;
11     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();}
12     while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar();
13     return f*x;
14 }
15 int n,m,f,rt,ans;
16 struct p{int pos[2]; bool operator < (const p &a)const{return pos[f]<a.pos[f];}}ps[maxn];
17 struct nd{p pos; int mx[2],mn[2],lc,rc;}nds[maxn*2];
18 int dis(p a,p b){return abs(a.pos[0]-b.pos[0])+abs(a.pos[1]-b.pos[1]);}
19 void update(int x){
20     inc(i,0,1){
21         if(nds[x].lc)
22             nds[x].mx[i]=max(nds[x].mx[i],nds[nds[x].lc].mx[i]),
23             nds[x].mn[i]=min(nds[x].mn[i],nds[nds[x].lc].mn[i]);
24         if(nds[x].rc)
25             nds[x].mx[i]=max(nds[x].mx[i],nds[nds[x].rc].mx[i]),
26             nds[x].mn[i]=min(nds[x].mn[i],nds[nds[x].rc].mn[i]);
27     }
28 }
29 int build(int l,int r,int now){
30     f=now; int mid=(l+r)>>1; nth_element(ps+l,ps+mid,ps+r+1);
31     inc(i,0,1)nds[mid].mx[i]=nds[mid].mn[i]=ps[mid].pos[i]; nds[mid].pos=ps[mid];
32     if(l<mid)nds[mid].lc=build(l,mid-1,now^1); if(mid<r)nds[mid].rc=build(mid+1,r,now^1);
33     update(mid); return mid;
34 }
35 void insert(int &x,p a,int now){
36     if(!x){x=++n; inc(i,0,1)nds[x].mx[i]=nds[x].mn[i]=a.pos[i]; nds[x].pos=a; return;}
37     f=now; if(a<nds[x].pos)insert(nds[x].lc,a,now^1);else insert(nds[x].rc,a,now^1); update(x);
38 }
39 int get(int x,p a){
40     int q=0; inc(i,0,1)q+=max(a.pos[i]-nds[x].mx[i],0),q+=max(nds[x].mn[i]-a.pos[i],0); return q;
41 }
42 void query(int x,p a){
43     ans=min(ans,dis(a,nds[x].pos)); int dl=INF-1,dr=INF-1;
44     if(nds[x].lc)dl=get(nds[x].lc,a); if(nds[x].rc)dr=get(nds[x].rc,a);
45     if(dl<dr){
46         if(ans>dl)query(nds[x].lc,a); if(ans>dr)query(nds[x].rc,a);
47     }else{
48         if(ans>dr)query(nds[x].rc,a); if(ans>dl)query(nds[x].lc,a);
49     }
50 }
51 int main(){
52     n=read(); m=read(); inc(i,1,n)ps[i].pos[0]=read(),ps[i].pos[1]=read(); rt=build(1,n,0);
53     inc(i,1,m){
54         int t=read(),x=read(),y=read();
55         if(t==1)insert(rt,(p){x,y},0);else ans=INF,query(rt,(p){x,y}),printf("%d\n",ans);
56     }
57     return 0;
58 }

20160906

时间: 2024-10-17 04:54:22

bzoj2648SJY摆棋子的相关文章

BZOJ 2648(SJY摆棋子-KD_Tree)

2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1180  Solved: 391 [Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=5000

【BZOJ2648】SJY摆棋子 [KD-tree]

SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N个初始棋子,和M个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的

【BZOJ-2648&amp;2716】SJY摆棋子&amp;天使玩偶 KD Tree

2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2459  Solved: 834[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000

SJY摆棋子&amp;&amp;[Violet 3]天使玩偶

SJY摆棋子 https://www.lydsy.com/JudgeOnline/problem.php?id=2648 [Violet 3]天使玩偶 https://www.lydsy.com/JudgeOnline/problem.php?id=2716 参考博客:https://blog.csdn.net/Littlewhite520/article/details/78284697 KDtree模板题,带插入 1 #include<iostream> 2 #include<cst

【BZOJ】2648: SJY摆棋子 &amp; 2716: [Violet 3]天使玩偶(kdtree)

http://www.lydsy.com/JudgeOnline/problem.php?id=2716 http://www.lydsy.com/JudgeOnline/problem.php?id=2648 双倍经验题... kdtree裸题吧.....今天学了下kdtree...感觉挺简单的.... 其实就是对几何图形进行剖分建树,而特殊在于,x和y轴轮流剖....这样可以提供很好的性质以便于查找... (一开始脑补了个treap代替kdtree.....显然我脑残了....写到一半发现这

Bzoj2648 SJY摆棋子

Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 3128  Solved: 1067 Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=500000个操作.对于每个白色棋子,输出距离这个

摆棋子

题意: 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. Input   输入含有多组测试数据.  每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目. n <= 8 , k <= n  当为-1 -1时表示输入结束.  随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区

【BZOJ2648】【kd_tree】SJY摆棋子

Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=500000个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离.同一个格子可能有多个棋子. Input 第一行两个数 N M 以后M行,每行3个数 t x y 如果t=1

BZOJ 2648 SJY摆棋子 / 2716 Violet 3 天使玩偶 K-D树

题目大意:平面上有一些点,问一个点周围离它最近的点的曼哈顿距离是多少.支持动态加点. 思路:CDQ分治可以离线解决,但是SJY是卡CDQ的,天使玩偶可以过.毕竟K-D树的O(sqrt(n))的时间复杂度摆在那. K-D树理解起来其实不难,有k个维度的时候,每一层按照一个维度排序,取出按照这个维度排序的中位数,当作这个块的根,然后将这个块分开.还有一个比较重要的东西就是估价函数,这个函数根据不同的题可能不同.股价函数的主要用途就是对搜索进行剪枝,如果估价函数就已经大于当前的最优答案了,那就不用搜这