#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1e9;
const int MAXN = 1e6;
//将题目的[0,1e6]偏移到[1,1e6+1]
const int H = 1e6 + 1;
int st[H * 4 + 5];
inline void push_up(int o) {
st[o] = min(st[o << 1], st[o << 1 | 1]);
}
void build(int o, int l, int r) {
if(l == r) {
st[o] = INF;
} else {
int mid = (l + r) >> 1;
build(o << 1, l, mid);
build(o << 1 | 1, mid + 1, r);
push_up(o);
}
}
void update(int o, int l, int r, int x, int v) {
if(l == r) {
st[o] = min(st[o], v);
} else {
int mid = (l + r) >> 1;
if(x <= mid)
update(o << 1, l, mid, x, v);
else
update(o << 1 | 1, mid + 1, r, x, v);
push_up(o);
}
}
void unupdate(int o, int l, int r, int x) {
if(l == r) {
st[o] = INF;
} else {
int mid = (l + r) >> 1;
if(x <= mid)
unupdate(o << 1, l, mid, x);
else
unupdate(o << 1 | 1, mid + 1, r, x);
push_up(o);
}
}
int query(int o, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) {
return st[o];
} else {
int mid = (l + r) >> 1, res = INF;
if(ql <= mid)
res = min(res, query(o << 1, l, mid, ql, qr));
if(qr >= mid + 1)
res = min(res, query(o << 1 | 1, mid + 1, r, ql, qr));
return res;
}
}
//ok
int qtop;
struct Query {
int t, op, x, y, ans;
bool operator<(const Query &q)const {
return x < q.x;
}
} q[MAXN + 5], tq[MAXN + 5];
inline int before_calc(int l, int r) {
int tqtop = 0, mid = (l + r) >> 1;
for(int i = l; i <= mid; ++i) {
if(q[i].op == 1)
tq[++tqtop] = q[i];
}
for(int i = mid + 1; i <= r; ++i) {
if(q[i].op == 2)
tq[++tqtop] = q[i];
}
sort(tq + 1, tq + 1 + tqtop);
return tqtop;
}
inline void after_calc(int tqtop) {
for(int i = 1; i <= tqtop; ++i) {
if(tq[i].op == 1)
//更新tq[j].y点的值为INF
unupdate(1, 1, H, tq[i].y);
else
q[tq[i].t].ans = tq[i].ans;
}
}
int calc_upleft(int tqtop) {
for(int i = 1, nxt; i <= tqtop; i = nxt) {
for(nxt = i + 1; nxt <= tqtop && tq[i].x == tq[nxt].x; ++nxt);
//只是左上角象限,同x全部先询问,然后再修改,消除同x的影响,其次询问的y是不包含自身的
//实际上,这道题不是计数,不是特别影响
for(int j = i; j < nxt; ++j) {
if(tq[j].op == 2)
//[tq[i].y+1,H]的答案
tq[j].ans = min(tq[i].ans, (tq[j].x - tq[j].y) + query(1, 1, H, tq[j].y + 1, H));
}
for(int j = i; j < nxt; ++j) {
if(tq[j].op == 1)
//更新tq[j].y点的值为负的tq[j].x+tq[j].y,这样取最大值的时候就变成原数的最小值
update(1, 1, H, tq[j].y, (-tq[j].x + tq[j].y));
}
}
after_calc(tqtop);
}
int calc_downleft(int tqtop) {
for(int i = 1, nxt; i <= tqtop; i = nxt) {
for(nxt = i + 1; nxt <= tqtop && tq[i].x == tq[nxt].x; ++nxt);
//左下角象限,包含x负半轴和y负半轴,同x全部先修改,然后再询问
//实际上,这道题不是计数,不是特别影响
for(int j = i; j < nxt; ++j) {
if(tq[j].op == 1)
//更新tq[j].y点的值为tq[j].x+tq[j].y
update(1, 1, H, tq[j].y, (-tq[j].x - tq[j].y));
}
for(int j = i; j < nxt; ++j) {
if(tq[j].op == 2)
//[1,tq[i].y]的答案
tq[j].ans = min(tq[i].ans, (tq[j].x + tq[j].y) + query(1, 1, H, 1, tq[j].y));
}
}
after_calc(tqtop);
}
int calc_upright(int tqtop) {
for(int i = tqtop, nxt; i >= 1; i = nxt) {
for(nxt = i - 1; nxt >= 1 && tq[i].x == tq[nxt].x; --nxt);
//右上角象限,包含x正半轴和y正半轴,同x全部先修改,然后再询问
//实际上,这道题不是计数,不是特别影响
for(int j = i; j > nxt; --j) {
if(tq[j].op == 1)
//更新tq[j].y点的值为负的tq[j].x+tq[j].y
update(1, 1, H, tq[j].y, (tq[j].x + tq[j].y));
}
for(int j = i; j > nxt; --j) {
if(tq[j].op == 2)
//[1,tq[i].y]的最大值
tq[j].ans = min(tq[i].ans, (-tq[j].x - tq[j].y) + query(1, 1, H, tq[j].y, H));
}
}
after_calc(tqtop);
}
int calc_downright(int tqtop) {
for(int i = tqtop, nxt; i >= 1; i = nxt) {
for(nxt = i - 1; nxt >= 1 && tq[i].x == tq[nxt].x; --nxt);
//右上角象限,包含x正半轴和y正半轴,同x全部先询问,然后再修改,并且询问的不含同y的
//实际上,这道题不是计数,不是特别影响
for(int j = i; j > nxt; --j) {
if(tq[j].op == 2)
//[1,tq[i].y]的最大值
tq[j].ans = min(tq[i].ans, (-tq[j].x + tq[j].y) + query(1, 1, H, 1, tq[j].y - 1));
}
for(int j = i; j > nxt; --j) {
if(tq[j].op == 1)
//更新tq[j].y点的值为tq[j].x+tq[j].y
update(1, 1, H, tq[j].y, (tq[j].x - tq[j].y));
}
}
after_calc(tqtop);
}
void solve(int l, int r) {
if(l == r)
return;
int mid = (l + r) >> 1;
solve(l, mid);
solve(mid + 1, r);
int tqtop = before_calc(l, r);
calc_upleft(tqtop);
// printf("After solveUL(%d,%d):\n",l,r);
// for(int i = 1; i <= qtop; ++i) {
// if(q[i].op == 2) {
// printf(" Query %d: %d\n",q[i].t, q[i].ans);
// }
// }
// printf("\n");
calc_downleft(tqtop);
// printf("After solveDL(%d,%d):\n",l,r);
// for(int i = 1; i <= qtop; ++i) {
// if(q[i].op == 2) {
// printf(" Query %d: %d\n",q[i].t, q[i].ans);
// }
// }
// printf("\n");
calc_upright(tqtop);
// printf("After solveUR(%d,%d):\n",l,r);
// for(int i = 1; i <= qtop; ++i) {
// if(q[i].op == 2) {
// printf(" Query %d: %d\n",q[i].t, q[i].ans);
// }
// }
// printf("\n");
calc_downright(tqtop);
// printf("After solveDR(%d,%d):\n",l,r);
// for(int i = 1; i <= qtop; ++i) {
// if(q[i].op == 2) {
// printf(" Query %d: %d\n",q[i].t, q[i].ans);
// }
// }
// printf("\n");
return;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m;
scanf("%d%d", &n, &m);
qtop = 0;
for(int i = 1; i <= n; ++i) {
int x, y;
scanf("%d%d", &x, &y);
++qtop;
q[qtop].op = 1;
q[qtop].t = qtop;
q[qtop].x = x + 1;
q[qtop].y = y + 1;
q[qtop].ans = INF;
}
for(int i = 1; i <= m; ++i) {
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
++qtop;
q[qtop].op = op;
q[qtop].t = qtop;
q[qtop].x = x + 1;
q[qtop].y = y + 1;
q[qtop].ans = INF;
}
build(1, 1, H);
solve(1, qtop);
for(int i = 1; i <= qtop; ++i) {
if(q[i].op == 2) {
printf("%d\n", q[i].ans);
}
}
}
AcWing - 254 - 天使玩偶 = CDQ分治
猜你喜欢
转载自www.cnblogs.com/Inko/p/11469513.html
今日推荐
周排行