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;
}