제출 #1329623

#제출 시각아이디문제언어결과실행 시간메모리
1329623vlomaczkIOI 바이러스 (JOI21_fever)C++20
100 / 100
1532 ms57296 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

ll best = 1;

struct Point {
	ll x, y;
};

ll inf = 1e18;

ll znajdz(vector<pair<ll, ll>> &M, ll b, ll Y, ll dv, ll w) {
    dv = max(dv, 1LL);
    ll x = w*dv;
    if(b) x = -x + 1;
    // cout << lower_bound(M.begin(), M.end(), make_pair(Y + x, -1LL)) - M.begin() << " - " << Y+x << "\n";
    // for(auto[a,b] : M) cout << a << " " << b << "\n";
    auto it = lower_bound(M.begin(), M.end(), make_pair(Y + x, -1LL)) - M.begin() - b;
    if(0<=it && it<(ll)M.size()) return M[it].second;
    return -1;
}

ll solve(ll n, vector<Point> &pkt) {
    // for(auto[a,b] : pkt) cout << a << " " << b << "\n";
    // cout << "\n";

	map<ll, vector<pair<ll, ll>>> mapa[4];
    auto get_val = [&](ll i, ll k) {
        if(k==0) return pkt[i].x;
        if(k==1) return pkt[i].y;
        if(k==2) return pkt[i].x + pkt[i].y;
        return pkt[i].x - pkt[i].y;
    };
    auto get_pair = [&](ll i, ll k) {
        return make_pair(k==1 ? pkt[i].x : pkt[i].y, i);
    };

    for(ll i=0; i<n; ++i) {
        auto[x, y] = pkt[i];
        for(ll k=0; k<4; ++k) mapa[k][get_val(i, k)].push_back(get_pair(i, k));
    }

    for(ll k=0; k<4; ++k) for(auto&[a,b] : mapa[k]) sort(b.begin(), b.end());
    priority_queue<pair<pair<ll, ll>, pair<ll, ll>>> pq;
    vector<vector<ll>> dist(n, vector<ll>(9, inf));
    dist[0][8] = 0;
    pq.push({{0,0}, {8, 0}});
    vector<ll> vis(n);
    auto dodaj = [&](ll dv, ll v, ll dir, ll k) {
        if(dist[v][dir] > dv) {
            dist[v][dir] = dv;
            pq.push({{-dv, v}, {dir, k}});
        }
    };

    while(pq.size()) {
        auto[stat1, stat2] = pq.top(); pq.pop();
        auto[dv, v] = stat1; auto[dir, k] = stat2; dv*= -1;
        if(dv!=dist[v][dir]) continue;
        vis[v] = 1;

        // cout << v << " " << k << " " << dir << " - " << dv << "\n";

        if(dir!=8) {
            auto it = lower_bound(mapa[dir/2][get_val(v, dir/2)].begin(), mapa[dir/2][get_val(v, dir/2)].end(), get_pair(v, dir/2));
            if(dir%2==0) {
                ++it;
                if(it!=mapa[dir/2][get_val(v, dir/2)].end()) {
                    ll moment = it->first - get_pair(v, dir/2).first;
                    if(dir < 4) moment /=2;
                    dodaj(moment + dv, it->second, dir, k);
                }
            } else {
                if(it!=mapa[dir/2][get_val(v, dir/2)].begin()) {
                    --it;
                    ll moment = get_pair(v, dir/2).first - it->first;
                    if(dir < 4) moment /=2;
                    dodaj(moment + dv, it->second, dir, k);
                }
            }
        }

        if(k < 2) {
            auto[x,y] = pkt[v];
            ll i;
            i = znajdz(mapa[0][x], k, y, dv, 2);
            if(i!=-1) {
                ll moment = pkt[i].y - y; moment/=2;
                if(k==1) moment *=-1;
                ll md = k;
                if(dist[i][md] > moment && moment >= dv) {
                    dist[i][md] = moment;
                    pq.push({{-moment, i}, {md, k^1}});
                }
            }
            i = znajdz(mapa[2][x+y], k, y, dv, 1);
            if(i!=-1) {
                ll moment = pkt[i].y - y;
                if(k==1) moment *=-1;
                ll md = 4+k;
                if(dist[i][md] > moment && moment >= dv) {
                    dist[i][md] = moment;
                    pq.push({{-moment, i}, {md, 2+k}});
                }
            }
            i = znajdz(mapa[3][x-y], k, y, dv, 1);
            if(i!=-1) {
                ll moment = pkt[i].y - y;
                if(k==1) moment *=-1;
                ll md = 6+k;
                if(dist[i][md] > moment && moment >= dv) {
                    dist[i][md] = moment;
                    pq.push({{-moment, i}, {md, 2+(k==0)}});
                }
            }
        } else {
            auto[x,y] = pkt[v];
            ll i = znajdz(mapa[1][y], k-2, x, dv, 2);
            if(i!=-1) {
                ll moment = abs(pkt[i].x - x); moment/=2;
                ll md = k;
                if(dist[i][md] > moment && moment >= dv) {
                    dist[i][md] = moment;
                    pq.push({{-moment, i}, {md, k^1}});
                }
            }

            i = znajdz(mapa[2][x+y], (k-2)^1, y, dv, 1);
            if(i!=-1) {
                ll moment = abs(pkt[i].y - y);
                ll md = (2+k)^1;
                if(dist[i][md] > moment && moment >= dv) {
                    dist[i][md] = moment;
                    pq.push({{-moment, i}, {md, (k==3)}});
                }
            }

            i = znajdz(mapa[3][x-y], k-2, y, dv, 1);
            if(i!=-1) {
                ll moment = abs(pkt[i].y - y);
                ll md = 4+k;
                if(dist[i][md] > moment && moment >= dv) {
                    dist[i][md] = moment;
                    pq.push({{-moment, i}, {md, (k==2)}});
                }
            }
        }
    }
    ll res = 0;
    for(ll i=0; i<n; ++i) res += vis[i];
    return res;
}

void rotate(ll n, vector<Point> &pkt) {
	for(ll i=0; i<n; ++i) {
		auto[x, y] = pkt[i];
		pkt[i] = {-y, x};
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	ll n;
	cin >> n;
	vector<Point> pkt(n);
	for(ll i=0; i<n; ++i) cin >> pkt[i].x >> pkt[i].y;
	for(ll i=n-1; i>=0; --i) {
		pkt[i].x -= pkt[0].x;
		pkt[i].y -= pkt[0].y;
		pkt[i].x *= 2;
		pkt[i].y *= 2;
	}
	for(ll i=0; i<4; ++i) {
		best = max(best, solve(n, pkt));
		rotate(n, pkt);
	}
	cout << best << "\n";

	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...