RT , 从黄学长那里初步学习到写KD树的姿势后自己摸索着写了指针+替罪羊版的,效率还可以….能够忍受。
BZOJ 4066 简单题
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define rep(i, x, y) for (int i = (x), _ = (y); i <= _; ++i)
#define down(i, x, y) for (int i = (x), _ = (y); i >= _; --i)
#define x first
#define y second
using namespace std;
typedef long long LL;
template<typename T> inline void up_max(T & x, T y) { x < y ? x = y : 0; }
template<typename T> inline void up_min(T & x, T y) { x > y ? x = y : 0; }
template<typename T>
inline void read(T & x)
{
char c;
while ((c = getchar()) < '0' || c > '9') ;
for (x = c - '0'; (c = getchar()) >= '0' && c <= '9'; x = x * 10 + c - '0');
}
const int N = 2e5 + 10;
namespace KD_Tree
{
struct node
{
node *ch[2];
int d[2], mx[2], my[2], size, val;
LL sum;
inline void push_up()
{
sum = val, size = 1;
rep (i, 0, 1) if (ch[i])
{
sum += ch[i]->sum, size += ch[i]->size;
up_min(mx[0], ch[i]->mx[0]);
up_max(mx[1], ch[i]->mx[1]);
up_min(my[0], ch[i]->my[0]);
up_max(my[1], ch[i]->my[1]);
}
}
}pool_node[N], *pool_top = pool_node;
node *del_pool[N], **del_top = del_pool;
inline node * newnode()
{
return del_top == del_pool ? ++pool_top : *(del_top--);
}
bool cmp_D;
struct Point
{
int d[2], val;
inline bool operator < (const Point & b) const
{
return d[cmp_D] < b.d[cmp_D];
}
} p[N];
int top = 0;
node *build(int l, int r, bool f)
{
node *o = newnode();
int mid = (l + r) >> 1;
cmp_D = f;
nth_element(p + l, p + mid, p + r + 1);
o->mx[0] = o->mx[1] = o->d[0] = p[mid].d[0];
o->my[0] = o->my[1] = o->d[1] = p[mid].d[1];
o->val = p[mid].val;
o->ch[0] = l < mid ? build(l, mid - 1, f ^ 1) : 0;
o->ch[1] = mid < r ? build(mid + 1, r, f ^ 1) : 0;
o->push_up();
return o;
}
void remove(node *o)
{
if (o->ch[0])
remove(o->ch[0]);
if (o->ch[1])
remove(o->ch[1]);
p[++top].val = o->val;
p[top].d[0] = o->d[0], p[top].d[1] = o->d[1];
*(++del_top) = o;
}
node ** rebuild_need;
bool rebuild_d;
void rebuild(node ** o)
{
top = 0, remove(*o);
*o = build(1, top, rebuild_d);
}
void insert(node *&o, int x, int y, int v, bool f)
{
if (!o)
{
o = newnode();
o->d[0] = o->mx[0] = o->mx[1] = x;
o->d[1] = o->my[0] = o->my[1] = y;
o->val = o->sum = v;
}
else if (o->d[0] == x && o->d[1] == y)
o->sum += v, o->val += v;
else
{
int d = !f ? o->d[0] < x : o->d[1] < y;
insert(o->ch[d], x, y, v, f ^ 1);
o->push_up();
if (o->ch[d]->size * 10 >= o->size * 7)
rebuild_need = &o, rebuild_d = f;
}
}
inline bool in(int x1, int y1, int x2, int y2, int a1, int b1, int a2, int b2)
{
return a1 <= x1 && b1 <= y1 && x2 <= a2 && y2 <= b2;
}
inline bool out(int x1, int y1, int x2, int y2, int a1, int b1, int a2, int b2)
{
return x2 < a1 || a2 < x1 || b2 < y1 || y2 < b1;
}
LL query(node *o, int x1, int y1, int x2, int y2)
{
if (!o || out(x1, y1, x2, y2, o->mx[0], o->my[0], o->mx[1], o->my[1]))
return 0;
if (in(o->mx[0], o->my[0], o->mx[1], o->my[1], x1, y1, x2, y2))
return o->sum;
LL ret = in(o->d[0], o->d[1], o->d[0], o->d[1], x1, y1, x2, y2) ? o->val : 0;
return ret + query(o->ch[0], x1, y1, x2, y2) + query(o->ch[1], x1, y1, x2, y2);
}
}
int main()
{
#ifdef LX_JUDGE
freopen("in.txt", "r", stdin);
#endif
using namespace KD_Tree;
node *root = 0;
int opt, x1, y1, x2, y2;
LL la = 0;
read(opt),
read(opt);
while (opt != 3)
{
switch (opt)
{
case 1 :
read(x1), read(y1), read(x2);
insert(root, x1 ^ la, y1 ^ la, x2 ^ la, 0);
if (rebuild_need)
{
rebuild(rebuild_need);
rebuild_need = 0;
}
break ;
case 2 :
read(x1), read(y1), read(x2), read(y2);
la = query(root, x1 ^ la, y1 ^ la, x2 ^ la, y2 ^ la);
printf("%lld\n", la);
break ;
}
read(opt);
}
return 0;
}
BZOJ 4533 数据
论查询最近最远点的姿势。
(不加rebuild的版本比rebuild版快100ms…我的姿势是不是有问题啊 TAT )
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define rep(i, x, y) for (int i = (x), _ = (y); i <= _; ++i)
#define down(i, x, y) for (int i = (x), _ = (y); i >= _; --i)
#define x first
#define y second
using namespace std;
typedef long long LL;
template<typename T> inline void up_max(T & x, T y) { x < y ? x = y : 0; }
template<typename T> inline void up_min(T & x, T y) { x > y ? x = y : 0; }
template<typename T>
inline void read(T & x)
{
char c;
while ((c = getchar()) < '0' || c > '9') ;
for (x = c - '0'; (c = getchar()) >= '0' && c <= '9'; x = x * 10 + c - '0');
}
const int inf = 2e9;
const int N = 2e5 + 10;
namespace KD_Tree
{
struct node
{
node *ch[2];
int d[2], mx[2], my[2], size;
inline void push_up()
{
size = 1;
rep (i, 0, 1) if (ch[i])
{
up_min(mx[0], ch[i]->mx[0]);
up_max(mx[1], ch[i]->mx[1]);
up_min(my[0], ch[i]->my[0]);
up_max(my[1], ch[i]->my[1]);
size += ch[i]->size;
}
}
}pool_node[N], *pool_top = pool_node;
node *del_pool[N], **del_top = del_pool;
inline node * newnode()
{
return del_top == del_pool ? ++pool_top : *(del_top--);
}
typedef pair<int, int > Point;
inline bool cmp_x(const Point & a, const Point & b) { return a.x < b.x; }
inline bool cmp_y(const Point & a, const Point & b) { return a.y < b.y; }
node **rebuild_need;
int rebuild_d;
Point stk[N];
int point_cnt;
node * build(int l, int r, bool f)
{
int mid = (l + r) >> 1;
node *o = newnode();
nth_element(stk + l, stk + mid, stk + r + 1, !f ? cmp_x : cmp_y);
o->d[0] = o->mx[0] = o->mx[1] = stk[mid].x;
o->d[1] = o->my[0] = o->my[1] = stk[mid].y;
o->ch[0] = l < mid ? build(l, mid - 1, f ^ 1) : 0;
o->ch[1] = mid < r ? build(mid + 1, r, f ^ 1) : 0;
o->push_up();
return o;
}
void remove(node *o)
{
if (o->ch[0])
remove(o->ch[0]);
if (o->ch[1])
remove(o->ch[1]);
stk[++point_cnt] = Point(o->d[0], o->d[1]);
*(++del_top) = o;
}
void rebuild()
{
point_cnt = 0;
remove(*rebuild_need);
*rebuild_need = build(1, point_cnt, rebuild_d);
rebuild_need = 0;
}
void insert(node *&o, int x, int y, bool f)
{
if (!o)
{
o = newnode();
o->d[0] = o->mx[0] = o->mx[1] = x;
o->d[1] = o->my[0] = o->my[1] = y;
}
else if (o->d[0] != x || o->d[1] != y)
{
int d = !f ? o->d[0] < x : o->d[1] < y;
insert(o->ch[d], x, y, f ^ 1);
o->push_up();
if (o->ch[d]->size * 10 >= o->size * 7)
rebuild_need = &o, rebuild_d = f;
}
}
Point P;
int ans;
int calc_mx(node *o)
{
int ret = 0;
ret += max(abs(o->mx[0] - P.x), abs(o->mx[1] - P.x));
ret += max(abs(o->my[0] - P.y), abs(o->my[1] - P.y));
return ret;
}
int calc_mn(node *o)
{
int ret = 0;
ret += max(P.x - o->mx[1], 0) + max(o->mx[0] - P.x, 0);
ret += max(P.y - o->my[1], 0) + max(o->my[0] - P.y, 0);
return ret;
}
void Query_Max(node *o)
{
up_max(ans, abs(o->d[0] - P.x) + abs(o->d[1] - P.y));
int dl = o->ch[0] ? calc_mx(o->ch[0]) : -inf;
int dr = o->ch[1] ? calc_mx(o->ch[1]) : -inf;
if (dl > dr)
{
if (dl > ans)
Query_Max(o->ch[0]);
if (dr > ans)
Query_Max(o->ch[1]);
}
else
{
if (dr > ans)
Query_Max(o->ch[1]);
if (dl > ans)
Query_Max(o->ch[0]);
}
}
void Query_Min(node *o)
{
up_min(ans, abs(o->d[0] - P.x) + abs(o->d[1] - P.y));
int dl = o->ch[0] ? calc_mn(o->ch[0]) : inf;
int dr = o->ch[1] ? calc_mn(o->ch[1]) : inf;
if (dl < dr)
{
if (dl < ans)
Query_Min(o->ch[0]);
if (dr < ans)
Query_Min(o->ch[1]);
}
else
{
if (dr < ans)
Query_Min(o->ch[1]);
if (dl < ans)
Query_Min(o->ch[0]);
}
}
node *root;
int Query(int x, int y, bool f)
{
P = Point(x, y);
if (f)
ans = -inf, Query_Max(root);
else
ans = inf, Query_Min(root);
return ans;
}
}
int main()
{
#ifdef LX_JUDGE
freopen("in.txt", "r", stdin);
#endif
using namespace KD_Tree;
read(point_cnt);
rep (i, 1, point_cnt)
read(stk[i].x), read(stk[i].y);
root = build(1, point_cnt, 0);
int Q, opt, x, y;
read(Q);
while (Q--)
{
read(opt), read(x), read(y);
switch (opt)
{
case 0 :
insert(root, x, y, 0);
if (rebuild_need)
rebuild();
break ;
case 1 :
printf("%d\n", Query(x, y, 0));
break ;
case 2 :
printf("%d\n", Query(x, y, 1));
break ;
}
}
return 0;
}