Description
腐女要过生日了,pty 想给腐女送礼物,但是腐女所在的教室离pty 的教室太远了,于是pty就拜托会动归和A星的djy帮忙送礼物。djy在学校建立了一个平面直角坐标系,他站在了(0,0)点,腐女在(x0,y0)点,djy每次只能往上下左右四个方向移动一步,中间有n栋矩形教学楼,每个教学楼给出两个对角的坐标,并且保证每栋教学楼的周围区域(如图所示)不会有别的教学楼,即djy可以绕一个教学楼走不会碰到任何障碍,现在djy 想知道从起点到终点不碰到任何教学楼,最短需要多少步。
Data Constraint
保证所有的y坐标在[-106,106]
所有的x坐标在[0,10^6]
70%的数据保证:n<=1000
100%的数据保证:n<=10^5
Solution
发现其实并不需要向左走,用线段树+扫描线,线段树表示到yi的最小步数,每次扫到矩阵右边界时,分别用从上往下走或从下往上走来更新。
Code
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define il inline
#define Int register int
#define max(x, y) (x > y) ? (x) : (y)
#define min(x, y) (x < y) ? (x) : (y)
using namespace std;
const int maxn1 = 2e5 + 7, maxn = 1e6 + 1;
struct code
{
int x,y,yy,z;
}a[maxn1];
struct code1
{
int bz,sum,bz1;
}f[maxn * 10];
int n, i, t, j, k, l, sx, sy, x, y, z, ans, bz;
il bool cmp(code x,code y)
{
return x.x < y.x || x.x == y.x && x.z > y.z;
}
il void build(int l, int r, int v)
{
int mid = (l + r) >> 1;
if (l == r)
{
f[v].sum = abs(l - maxn);
return;
}
build(l, mid, v << 1);
build(mid + 1, r, (v << 1) | 1);
}
il void pushdown(int v)
{
if (f[v].bz == 1) f[v << 1].bz = f[(v << 1) | 1].bz = 1;
else if (f[v].bz == 2) f[v << 1].bz = f[(v << 1) | 1].bz = 2, f[v << 1].bz1 = f[(v << 1) | 1].bz1 = f[v].bz1;
else if (f[v].bz == 3) f[v << 1].bz = f[(v << 1) | 1].bz = 3, f[v << 1].bz1 = f[(v << 1) | 1].bz1 = f[v].bz1;
}
il void change(int l, int r, int v, int x, int y)
{
int mid = (l + r) >> 1;
if (x > y) return;
if (f[v].bz)
{
if (l != r) pushdown(v);
else if (f[v].bz == 1) f[v].sum = maxn * 1000;
else if (f[v].bz == 2) f[v].sum = f[v].bz1 + l;
else f[v].sum = f[v].bz1 - l;
f[v].bz = 0;
}
if (l >= x && r <= y)
{
f[v].bz = z;
if (z != 1) f[v].bz1 = t;
return;
}
if (l <= y && mid >= x) change(l, mid, v << 1, x, y);
if (mid < y && r >= x) change(mid + 1, r, (v << 1) | 1, x, y);
}
il void find(int l, int r, int v, int x)
{
int mid = (l + r) >> 1;
if (f[v].bz)
{
if (l != r) pushdown(v);
else if (f[v].bz == 1) f[v].sum = maxn * 1000;
else if (f[v].bz == 2) f[v].sum = f[v].bz1 + l;
else f[v].sum = f[v].bz1 - l;
f[v].bz = 0;
}
if (l == r)
{
t = f[v].sum;
return;
}
if (mid >= x) find(l, mid, v << 1, x);
else find(mid + 1, r, (v << 1) | 1, x);
}
int main()
{
scanf("%d%d%d", &sx, &sy, &n);
sy += maxn;
for (Int i = 1; i <= n; ++ i)
{
scanf("%d%d%d%d", &a[i].x, &a[i].y, &a[i + n].x, &a[i].yy), a[i].y += maxn, a[i].yy += maxn;
if (a[i + n].x < a[i].x) a[i + n].z = 1;
else a[i].z = 1;
if (a[i].y > a[i].yy) swap(a[i].y, a[i].yy);
a[i + n].y = a[i].y, a[i + n].yy = a[i].yy;
}
sort(a + 1, a + (n << 1) + 1, cmp);
bz = 0;
for (Int i = 1; i <= n << 1; ++ i)
{
if (a[i].x > sx) break;
if (!bz) build(1, maxn << 1, 1);
if (a[i].z) z = 1, change(1, maxn << 1, 1, a[i].y, a[i].yy);
else
{
t = z = 0;
find(1, maxn << 1, 1, a[i].y - 1);k = t;
find(1, maxn << 1, 1, a[i].yy + 1);swap(t, k);
x = (a[i].y + a[i].yy - t + k) >> 1;
t -= a[i].y - 1;
z = 2;
change(1, maxn << 1, 1, a[i].y, min(a[i].yy, x));z = 3;t = k + a[i].yy + 1;
change(1, maxn << 1, 1, max(a[i].y, x + 1), a[i].yy);
}
++ bz;
}
t = 0;
z = 1;
ans = 1e9;
find(1, maxn << 1, 1, sy);
t += sx;
printf("%d\n", t);
return 0;
}