# |
제출 시각 |
아이디 |
문제 |
언어 |
결과 |
실행 시간 |
메모리 |
122786 |
2019-06-29T09:22:43 Z |
윤교준(#3000) |
Golf (JOI17_golf) |
C++14 |
|
85 ms |
31932 KB |
#include <bits/stdc++.h>
#define eb emplace_back
#define sz(V) ((int)(V).size())
#define allv(V) ((V).begin()),((V).end())
#define sorv(V) sort(allv(V))
#define univ(V) (V).erase(unique(allv(V)),(V).end())
#define upmin(a,b) (a)=min((a),(b))
#define upmax(a,b) (a)=max((a),(b))
#define INF (0x3f3f3f3f)
#define INFLL (0x3f3f3f3f3f3f3f3fll)
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
inline void fg(vector<pii> G[], int a, int b, int c) { G[a].eb(b, c); G[b].eb(a, c); }
const int MAXN = 100055;
const int MAXK = MAXN*3*4;
struct LNEEVT {
LNEEVT(ll x, ll sy, ll ey)
: x(x), sy(sy), ey(ey) {}
ll x, sy, ey;
bool operator < (const LNEEVT &t) const {
return x < t.x;
}
};
vector<pii> G[MAXK];
int DP[MAXK];
int K, Sidx, Eidx;
vector<pair<pll, pll>> EDV;
vector<pll> PV;
ll SX[MAXN], SY[MAXN], EX[MAXN], EY[MAXN];
ll MNSX, MXSX, MNSY, MXSY;
ll MNEX, MXEX, MNEY, MXEY;
ll PSX, PSY, PEX, PEY;
int N, Ans = INF;
inline int getI(const pll &p) { return int(lower_bound(allv(PV), p) - PV.begin()); }
inline int getDr(const pll &a, const pll &b) {
if(a.first == b.first) return a.second < b.second ? 0 : 2;
return a.first < b.first ? 1 : 3;
}
inline bool isCross(ll ax, ll asy, ll aey, ll bsx, ll bex, ll by) {
return bsx <= ax && ax <= bex && asy <= by && by <= aey;
}
bool isPathOK(pll a, pll b) {
if(a.first == b.first) {
if(a.second > b.second) swap(a, b);
for(int i = 1; i <= N; i++) {
if(isCross(a.first, a.second, b.second, SX[i]+1, EX[i]-1, SY[i]+1)) return false;
if(isCross(a.first, a.second, b.second, SX[i]+1, EX[i]-1, EY[i]-1)) return false;
}
return true;
}
if(a.first > b.first) swap(a, b);
for(int i = 1; i <= N; i++) {
if(isCross(SX[i]+1, SY[i]+1, EY[i]-1, a.first, b.first, a.second)) return false;
if(isCross(EX[i]-1, SY[i]+1, EY[i]-1, a.first, b.first, a.second)) return false;
}
return true;
}
bool isAnswerOne() {
if(PSX != PEX && PSY != PEY) return false;
return isPathOK({PSX, PSY}, {PEX, PEY});
}
bool isAnswerTwo() {
return (isPathOK({PSX, PSY}, {PSX, PEY}) && isPathOK({PSX, PEY}, {PEX, PEY}))
|| (isPathOK({PSX, PSY}, {PEX, PSY}) && isPathOK({PEX, PSY}, {PEX, PEY}));
}
bool tryForThree(ll sx, ll ex, ll sy, ll ey, vector<pll> &V) {
if(sy > ey) return false;
if(V.empty()) return true;
vector<ll> YV;
YV.eb(sy); YV.eb(ey); YV.eb(ey+1);
for(auto &v : V) {
YV.eb(v.first);
YV.eb(v.second+1);
}
sorv(YV); univ(YV);
int n = sz(YV);
vector<int> S(n, 0);
for(auto &v : V) {
S[int(lower_bound(allv(YV), v.first) - YV.begin())]++;
S[int(lower_bound(allv(YV), v.second+1) - YV.begin())]--;
}
if(!S[0]) return true;
for(int i = 1; i < n-1; i++) {
S[i] += S[i-1];
if(!S[i]) return true;
}
return false;
}
bool isAnswerThree() {
{
vector<pll> V;
ll mn = max(MNSY, MNEY), mx = min(MXSY, MXEY);
for(int i = 1; i <= N; i++) {
if(PSX <= SX[i]+1 && SX[i]+1 <= PEX) {
ll s = max(SY[i]+1, mn), e = min(EY[i]-1, mx);
if(s <= e) V.eb(s, e);
}
}
if(tryForThree(PSX, PEX, mn, mx, V)) return true;
}
{
vector<pll> V;
ll mn = max(MNSX, MNEX), mx = min(MXSX, MXEX);
for(int i = 1; i <= N; i++) {
if(PSY <= SY[i]+1 && SY[i]+1 <= PEY) {
ll s = max(SX[i]+1, mn), e = min(EX[i]-1, mx);
if(s <= e) V.eb(s, e);
}
}
if(tryForThree(PSY, PEY, mn, mx, V)) return true;
}
return false;
}
void findMNMXXY() {
MNSX = MNSY = MNEX = MNEY = -INFLL;
MXSX = MXSY = MXEX = MXEY = INFLL;
for(int i = 1; i <= N; i++) {
if(SX[i] <= PSX && PSX <= EX[i]) {
if(PSY <= SY[i]) upmin(MXSY, SY[i]);
if(EY[i] <= PSY) upmax(MNSY, EY[i]);
}
if(SY[i] <= PSY && PSY <= EY[i]) {
if(PSX <= SX[i]) upmin(MXSX, SX[i]);
if(EX[i] <= PSX) upmax(MNSX, EX[i]);
}
if(SX[i] <= PEX && PEX <= EX[i]) {
if(PEY <= SY[i]) upmin(MXEY, SY[i]);
if(EY[i] <= PEY) upmax(MNEY, EY[i]);
}
if(SY[i] <= PEY && PEY <= EY[i]) {
if(PEX <= SX[i]) upmin(MXEX, SX[i]);
if(EX[i] <= PEX) upmax(MNEX, EX[i]);
}
}
}
void makePoints(vector<LNEEVT> &EV, vector<pll> &PV) {
set<ll> CH;
sorv(EV);
for(auto &ev : EV) {
ll s = ev.sy, e = ev.ey, x = ev.x;
PV.eb(x, s); PV.eb(x, e);
for(auto it = CH.lower_bound(s); CH.end() != it && *it <= e;) {
PV.eb(x, *it);
it = CH.erase(it);
}
CH.insert(s); CH.insert(e);
}
}
void makePoints() {
PV.eb(PSX, PSY); PV.eb(PEX, PEY);
if(-INFLL < MNSX) PV.eb(MNSX, PSY);
if(MXSX < INFLL) PV.eb(MXSX, PSY);
if(-INFLL < MNSY) PV.eb(PSX, MNSY);
if(MXSY < INFLL) PV.eb(PSX, MXSY);
if(-INFLL < MNEX) PV.eb(MNEX, PEY);
if(MXEX < INFLL) PV.eb(MXEX, PEY);
if(-INFLL < MNEY) PV.eb(PEX, MNEY);
if(MXEY < INFLL) PV.eb(PEX, MXEY);
{
vector<LNEEVT> EV;
vector<pll> V;
for(int i = 1; i <= N; i++) {
EV.eb(SX[i], SY[i], EY[i]);
EV.eb(EX[i], SY[i], EY[i]);
}
makePoints(EV, V);
for(auto &v : V) PV.eb(v.first, v.second);
}
{
vector<LNEEVT> EV;
vector<pll> V;
for(int i = 1; i <= N; i++) {
EV.eb(-SX[i], SY[i], EY[i]);
EV.eb(-EX[i], SY[i], EY[i]);
}
makePoints(EV, V);
for(auto &v : V) PV.eb(-v.first, v.second);
}
{
vector<LNEEVT> EV;
vector<pll> V;
for(int i = 1; i <= N; i++) {
EV.eb(SY[i], SX[i], EX[i]);
EV.eb(EY[i], SX[i], EX[i]);
}
makePoints(EV, V);
for(auto &v : V) PV.eb(v.second, v.first);
}
{
vector<LNEEVT> EV;
vector<pll> V;
for(int i = 1; i <= N; i++) {
EV.eb(-SY[i], SX[i], EX[i]);
EV.eb(-EY[i], SX[i], EX[i]);
}
makePoints(EV, V);
for(auto &v : V) PV.eb(v.second, -v.first);
}
sorv(PV); univ(PV);
}
void makeEdges(vector<pll> &PV, vector<pll> &BV, vector<pair<pll, pll>> &EV) {
set<ll> CH;
sorv(PV); sorv(BV);
for(int s = 0, e, pv = 0, n = sz(PV), m = sz(BV); s < n;) {
if(pv < m && BV[pv] < PV[s]) {
auto it = CH.find(BV[pv].second);
if(CH.end() != it) CH.erase(it);
else CH.insert(BV[pv].second);
pv++;
continue;
}
for(e = s+1; e < n && PV[s].first == PV[e].first; e++);
auto it = CH.begin();
for(int i = s+1; i < e; i++) {
for(; CH.end() != it && *it < PV[i-1].second; it++);
if(CH.end() == it || PV[i].second < *it) EV.eb(PV[i-1], PV[i]);
}
s = e;
}
}
void makeEdges() {
{
vector<pair<pll, pll>> EV;
vector<pll> BV;
for(int i = 1; i <= N; i++) {
if(SX[i]+2 == EX[i]) continue;
BV.eb(SX[i]+1, SY[i]+1);
BV.eb(EX[i]-1, SY[i]+1);
if(SY[i]+2 < EY[i]) {
BV.eb(SX[i]+1, EY[i]-1);
BV.eb(EX[i]-1, EY[i]-1);
}
}
makeEdges(PV, BV, EV);
for(auto &ed : EV) {
if(ed.first > ed.second) swap(ed.first, ed.second);
EDV.eb(ed);
}
}
{
vector<pair<pll, pll>> EV;
vector<pll> BV;
for(auto &v : PV) swap(v.first, v.second);
for(int i = 1; i <= N; i++) {
if(SY[i]+2 == EY[i]) continue;
BV.eb(SY[i]+1, SX[i]+1);
BV.eb(EY[i]-1, SX[i]+1);
if(SX[i]+2 < EX[i]) {
BV.eb(SY[i]+1, EX[i]-1);
BV.eb(EY[i]-1, EX[i]-1);
}
}
makeEdges(PV, BV, EV);
for(auto &v : PV) swap(v.first, v.second);
sorv(PV);
for(auto &ed : EV) {
swap(ed.first.first, ed.first.second);
swap(ed.second.first, ed.second.second);
if(ed.first > ed.second) swap(ed.first, ed.second);
EDV.eb(ed);
}
}
sorv(EDV); univ(EDV);
}
void makeGraph() {
K = sz(PV) << 2;
fill(DP, DP+K, INF);
Sidx = getI({PSX, PSY});
Eidx = getI({PEX, PEY});
for(int i = 0; i < 4; i++) DP[(Sidx<<2)|i] = 1;
for(int i = 0; i < K; i += 4) {
for(int a = 0; a < 4; a++) for(int b = a+1; b < 4; b++)
fg(G, i|a, i|b, 1);
}
for(auto &ed : EDV) {
int a = getI(ed.first), b = getI(ed.second);
int dr = getDr(ed.first, ed.second);
G[(a<<2)|dr].eb((b<<2)|dr, 0);
G[(b<<2)|(dr^2)].eb((a<<2)|(dr^2), 0);
}
}
void spreadStarts() {
// TODO for O(N lgN)
for(int i = sz(PV); i--;) {
const pll &p = PV[i];
if(MNSX <= p.first && p.first <= MXSX && p.second != PSY) {
if(isPathOK({p.first, PSY}, p)) {
if(PSY < p.second) upmin(DP[i<<2], 2);
else upmin(DP[(i<<2)|2], 2);
}
}
if(MNSY <= p.second && p.second <= MXSY && p.first != PSX) {
if(isPathOK({PSX, p.second}, p)) {
if(PSX < p.first) upmin(DP[(i<<2)|1], 2);
else upmin(DP[(i<<2)|3], 2);
}
}
}
}
void runDijk() {
priority_queue<pii, vector<pii>, greater<pii>> PQ;
for(int i = 0; i < K; i++) if(DP[i] < 3) PQ.push({DP[i], i});
for(int idx, dst; !PQ.empty();) {
tie(dst, idx) = PQ.top(); PQ.pop();
if(DP[idx] < dst) continue;
for(auto &ed : G[idx]) {
int nidx = ed.first;
int ndst = dst + ed.second;
if(DP[nidx] <= ndst) continue;
DP[nidx] = ndst;
PQ.push({ndst, nidx});
}
}
}
void calAns() {
for(int i = 0; i < 4; i++) upmin(Ans, DP[(Eidx<<2)|i]);
for(int i = sz(PV); i--;) {
const pll &p = PV[i];
if(MNEX <= p.first && p.first <= MXEX && p.second != PEY) {
if(isPathOK({p.first, PEY}, p)) {
if(PEY < p.second) upmin(Ans, DP[(i<<2)|2] + 1);
else upmin(Ans, DP[i<<2] + 1);
}
}
if(MNEY <= p.second && p.second <= MXEY && p.first != PEX) {
if(isPathOK({PEX, p.second}, p)) {
if(PEX < p.first) upmin(Ans, DP[(i<<2)|3] + 1);
else upmin(Ans, DP[(i<<2)|1] + 1);
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin >> PSX >> PSY >> PEX >> PEY >> N;
for(int i = 1; i <= N; i++) cin >> SX[i] >> EX[i] >> SY[i] >> EY[i];
if(PSX > PEX) {
PSX = -PSX; PEX = -PEX;
for(int i = 1; i <= N; i++) {
SX[i] = -SX[i];
EX[i] = -EX[i];
}
}
if(PSY > PEY) {
PSY = -PSY; PEY = -PEY;
for(int i = 1; i <= N; i++) {
SY[i] = -SY[i];
EY[i] = -EY[i];
}
}
for(int i = 1; i <= N; i++) {
if(SX[i] > EX[i]) swap(SX[i], EX[i]);
if(SY[i] > EY[i]) swap(SY[i], EY[i]);
}
{
vector<int> XV;
XV.eb(PSX); XV.eb(PEX);
for(int i = 1; i <= N; i++) {
XV.eb(SX[i]);
XV.eb(EX[i]);
}
sorv(XV); univ(XV);
PSX = int(lower_bound(allv(XV), PSX) - XV.begin());
PEX = int(lower_bound(allv(XV), PEX) - XV.begin());
for(int i = 1; i <= N; i++) {
SX[i] = int(lower_bound(allv(XV), SX[i]) - XV.begin());
EX[i] = int(lower_bound(allv(XV), EX[i]) - XV.begin());
}
}
{
vector<int> YV;
YV.eb(PSY); YV.eb(PEY);
for(int i = 1; i <= N; i++) {
YV.eb(SY[i]);
YV.eb(EY[i]);
}
sorv(YV); univ(YV);
PSY = int(lower_bound(allv(YV), PSY) - YV.begin());
PEY = int(lower_bound(allv(YV), PEY) - YV.begin());
for(int i = 1; i <= N; i++) {
SY[i] = int(lower_bound(allv(YV), SY[i]) - YV.begin());
EY[i] = int(lower_bound(allv(YV), EY[i]) - YV.begin());
}
}
PSX <<= 1; PSY <<= 1; PEX <<= 1; PEY <<= 1;
for(int i = 1; i <= N; i++) {
SX[i] <<= 1; SY[i] <<= 1;
EX[i] <<= 1; EY[i] <<= 1;
}
if(isAnswerOne()) {
puts("1");
exit(0);
}
if(isAnswerTwo()) {
puts("2");
exit(0);
}
findMNMXXY();
if(isAnswerThree()) {
puts("3");
exit(0);
}
makePoints();
makeEdges();
/*
for(auto &p : PV) printf("%lld %lld\n", p.first, p.second);
for(auto &ed : EDV) printf("%lld %lld <-> %lld %lld\n", ed.first.first, ed.first.second, ed.second.first, ed.second.second);
*/
makeGraph();
spreadStarts();
runDijk();
calAns();
cout << Ans << endl;
return 0;
}
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
31 ms |
28512 KB |
Output is correct |
2 |
Correct |
22 ms |
28544 KB |
Output is correct |
3 |
Correct |
21 ms |
28544 KB |
Output is correct |
4 |
Correct |
26 ms |
28544 KB |
Output is correct |
5 |
Incorrect |
85 ms |
31932 KB |
Output isn't correct |
6 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
31 ms |
28512 KB |
Output is correct |
2 |
Correct |
22 ms |
28544 KB |
Output is correct |
3 |
Correct |
21 ms |
28544 KB |
Output is correct |
4 |
Correct |
26 ms |
28544 KB |
Output is correct |
5 |
Incorrect |
85 ms |
31932 KB |
Output isn't correct |
6 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
31 ms |
28512 KB |
Output is correct |
2 |
Correct |
22 ms |
28544 KB |
Output is correct |
3 |
Correct |
21 ms |
28544 KB |
Output is correct |
4 |
Correct |
26 ms |
28544 KB |
Output is correct |
5 |
Incorrect |
85 ms |
31932 KB |
Output isn't correct |
6 |
Halted |
0 ms |
0 KB |
- |