2648: SJY摆棋子
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 5570 Solved: 1952
[ Submit][ Status][ Discuss]
Description
这天,SJY显得无聊。在家自己玩。在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。
Input
第一行两个数 N M
以后M行,每行3个数 t x y
如果t=1 那么放下一个黑色棋子
如果t=2 那么放下一个白色棋子
Output
对于每个T=2 输出一个最小距离
Sample Input
2 3
1 1
2 3
2 1 2
1 3 3
2 4 2
1 1
2 3
2 1 2
1 3 3
2 4 2
Sample Output
1
2
HINT
kdtree可以过
Source
这题有两种做法:
第一种是把曼哈顿距离转换成切比雪夫距离,然后直接上个数据结构维护查询就好了(然而lz并没有去实现
第二种是用kd tree。。。
这里kd tree就是一个优化剪枝的作用。。。(lz现在才明白
然后对于这题因为有插入的操作,所以分割平面的直线要随便取,即随便取切x轴或是切y轴(这样期望的复杂度才比较小
然后就是模板==
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
typedef double DL;
const int INF = 2147483647;
const int maxn = 1000010;
struct data{
int x,y;
}p[maxn];
int n,m,rt,tot,cnt;
int s[maxn][3],ma[maxn][3],mi[maxn][3],lc[maxn],rc[maxn],D[maxn];
int a[3],ans;
inline int getint()
{
int ret = 0,f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
ret = ret * 10 + c - '0',c = getchar();
return ret * f;
}
inline DL sqr(const DL &x)
{
return x * x;
}
inline bool cmpx(const data &a,const data &b)
{
return a.x < b.x;
}
inline bool cmpy(const data &a,const data &b)
{
return a.y < b.y;
}
inline void maintain(const int &o)
{
for (int i = 1; i <= 2; i++)
{
if (lc[o]) ma[o][i] = max(ma[lc[o]][i],ma[o][i]);
if (rc[o]) ma[o][i] = max(ma[rc[o]][i],ma[o][i]);
if (lc[o]) mi[o][i] = min(mi[lc[o]][i],mi[o][i]);
if (rc[o]) mi[o][i] = min(mi[rc[o]][i],mi[o][i]);
}
}
inline void build(int &o,int l,int r,int k)
{
if (l > r) return;
if (!o) o = ++tot;
int mid = l + r >> 1;
D[o] = k + 1;
if (!k) nth_element(p + l,p + mid,p + r + 1,cmpx);
else nth_element(p + l,p + mid,p + r + 1,cmpy);
s[o][1] = ma[o][1] = mi[o][1] = p[mid].x;
s[o][2] = ma[o][2] = mi[o][2] = p[mid].y;
build(lc[o],l,mid - 1,k ^ 1);
build(rc[o],mid + 1,r,k ^ 1);
maintain(o);
}
inline int min(const int x,const int y)
{
return x < y ? x : y;
}
inline int abs(const int x)
{
return x < 0 ? -x : x;
}
inline void putint(const int &x)
{
if (x >= 10) putint(x / 10);
putchar(x % 10 + '0');
}
inline int getval(int o,int a[3])
{
if (!o) return INF;
int ret = INF,sum = 0;
int t1 = mi[o][1] <= a[1] && a[1] <= ma[o][1];
int t2 = mi[o][2] <= a[2] && a[2] <= ma[o][2];
ret = min(ret,(t1 ? 0 : abs(a[1] - ma[o][1])) + (t2 ? 0 : abs(a[2] - ma[o][2])));
ret = min(ret,(t1 ? 0 : abs(a[1] - ma[o][1])) + (t2 ? 0 : abs(a[2] - mi[o][2])));
ret = min(ret,(t1 ? 0 : abs(a[1] - mi[o][1])) + (t2 ? 0 : abs(a[2] - ma[o][2])));
ret = min(ret,(t1 ? 0 : abs(a[1] - mi[o][1])) + (t2 ? 0 : abs(a[2] - mi[o][2])));
return ret;
}
inline void query(int o,int a[3])
{
if (!o) return;
ans = min(ans,abs(s[o][1] - a[1]) + abs(s[o][2] - a[2]));
int x1 = getval(lc[o],a),x2 = getval(rc[o],a);
if (x1 < x2)
{
if (x1 < ans) query(lc[o],a);
if (x2 < ans) query(rc[o],a);
}
else
{
if (x2 < ans) query(rc[o],a);
if (x1 < ans) query(lc[o],a);
}
}
inline void insert(int &o,int a[3],int k)
{
if (!o)
{
o = ++tot;
D[o] = k + 1;
s[o][1] = ma[o][1] = mi[o][1] = a[1];
s[o][2] = ma[o][2] = mi[o][2] = a[2];
return;
}
if (a[D[o]] < s[o][D[o]]) insert(lc[o],a,k ^ 1);
else insert(rc[o],a,k ^ 1);
maintain(o);
}
int main()
{
n = getint(); m = getint();
for (int i = 1; i <= n; i++)
p[i].x = getint() , p[i].y = getint();
build(rt,1,n,0);
for (int i = 1; i <= m; i++)
{
int c = getint(); a[1] = getint(); a[2] = getint();
if (c == 1) insert(rt,a,0);
else
{
ans = INF;
query(rt,a);
putint(ans);
putchar('\n');
}
}
return 0;
}