Submission #579030

#TimeUsernameProblemLanguageResultExecution timeMemory
579030MetalPowerIOI 바이러스 (JOI21_fever)C++14
69 / 100
2360 ms90860 KiB
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define pii pair<ll, ll>
#define pli pair<ll, pii>
#define fi first
#define se second

const ll MX = 3e5 + 10;
const ll INF = 1e18;

ll N, X[MX], Y[MX], direction[MX];

// Right, Down, Left, Up

map<ll, vector<pii>> vert[4], hori[4], incd[4], decd[4];
ll dist[MX * 3]; bool colored[MX], vis[MX * 3];

vector<pii> adj[MX * 3];
// node, weight

void buildEdge(vector<pii>& v, ll inc, ll dir){ // dir 0 line, 1 clockwise, 2 counterclockwise
	if(inc == 1){
		for(ll i = 1; i < v.size(); i++){
			ll w = (v[i].fi - v[i - 1].fi) / (dir == 0 ? 2ll : 1ll);
			adj[(ll) 3 * v[i - 1].se + dir].push_back({(ll) 3 * v[i].se + dir, w});
		}
	}else{
		for(ll i = v.size() - 1; i > 0; i--){
			ll w = (v[i].fi - v[i - 1].fi) / (dir == 0 ? 2ll : 1ll);
			adj[(ll) 3 * v[i].se + dir].push_back({(ll) 3 * v[i - 1].se + dir, w});
		}
	}
}

ll absol(ll x){
	return x > 0 ? x : -x;
}

pii trav(vector<pii>& v, ll node, ll d, ll dir){
	ll idx = lower_bound(v.begin(), v.end(), make_pair(d, (ll) -1)) - v.begin();
	if(idx == v.size()) return make_pair(-1, 0);
	ll nxt = v[idx].se, mdist;
	mdist = (absol(X[node] - X[nxt]) + absol(Y[node] - Y[nxt])) / 2;
	return {nxt * 3 + dir, mdist};
}

pii dtrav(vector<pii>& v, ll node, ll d, ll dir){
	ll idx = lower_bound(v.begin(), v.end(), make_pair(d + 1, (ll) -1)) - v.begin() - 1;
	if(idx == -1) return make_pair(-1, 0);
	ll nxt = v[idx].se, mdist;
	mdist = (absol(X[node] - X[nxt]) + absol(Y[node] - Y[nxt])) / 2;
	return {nxt * 3 + dir, mdist};
}

ll solve(){

	memset(vis, 0, sizeof vis);
	for(ll i = 0; i < 3 * MX; i++){
		adj[i].clear();
		dist[i] = INF;
		if(i < MX) colored[i] = false;
	}

	direction[0] = 0;
	for(ll i = 1; i < N; i++){
		ll _x = X[i] / 2, _y = Y[i] / 2;
		if(_x < 0 && (_y <= 0 ? -_y <= -_x : _y <= -_x)) direction[i] = 0;
		else if(_y > 0 && (_x <= 0 ? -_x <= _y - 1 : _x <= _y)) direction[i] = 1;
		else if(_x > 0 && (_y <= 0 ? -_y <= _x - 1 : _y <= _x - 1)) direction[i] = 2;
		else if(_y < 0 && (_x <= 0 ? -_x <= -_y - 1 : _x <= -_y)) direction[i] = 3;
		else assert(false);
	}

	for(ll d = 0; d < 4; d++){
		vert[d].clear(), hori[d].clear(), incd[d].clear(), decd[d].clear();
	}

	for(ll i = 0; i < N; i++){
		vert[direction[i]][X[i]].push_back({Y[i], i});
		hori[direction[i]][Y[i]].push_back({X[i], i});
		incd[direction[i]][X[i] - Y[i]].push_back({X[i], i});
		decd[direction[i]][X[i] + Y[i]].push_back({X[i], i});
	}

	for(ll d = 0; d < 4; d++){
		for(auto& x : vert[d]) sort(x.se.begin(), x.se.end());
		for(auto& x : hori[d]) sort(x.se.begin(), x.se.end());
		for(auto& x : incd[d]) sort(x.se.begin(), x.se.end());
		for(auto& x : decd[d]) sort(x.se.begin(), x.se.end());
	}

	// Right, Down, Left, Up
	{
		for(auto& x : hori[0]) buildEdge(x.se, 0, 0);
		for(auto& x : vert[1]) buildEdge(x.se, 1, 0); 
		for(auto& x : hori[2]) buildEdge(x.se, 1, 0);
		for(auto& x : vert[3]) buildEdge(x.se, 0, 0);
	}

	{
		for(auto& x : incd[0]) buildEdge(x.se, 0, 2);
		for(auto& x : incd[1]) buildEdge(x.se, 1, 1);
		for(auto& x : incd[2]) buildEdge(x.se, 1, 2);
		for(auto& x : incd[3]) buildEdge(x.se, 0, 1);
	}

	{
		for(auto& x : decd[0]) buildEdge(x.se, 0, 1);
		for(auto& x : decd[1]) buildEdge(x.se, 0, 2);
		for(auto& x : decd[2]) buildEdge(x.se, 1, 1);
		for(auto& x : decd[3]) buildEdge(x.se, 1, 2);
	}

	priority_queue<pii, vector<pii>, greater<pii>> pq;

	pq.push({0, 0});
	dist[0] = 0;

	ll cnt = 0;

	while(!pq.empty()){

		// place-holder node
		ll cd = pq.top().fi; ll pd = pq.top().se; pq.pop();
		
		if(!vis[pd]){ // Reachable edge
			vis[pd] = true;
			for(auto nxt : adj[pd]){
				ll nd = cd + nxt.se;
				if(dist[nxt.fi] > nd){
					dist[nxt.fi] = nd;
					pq.push({dist[nxt.fi], nxt.fi});
				}
			}
		}

		// Right, Down, Left, Up

		ll node = pd / 3;
		if(!colored[node]){ // isColored
			// find collision

			pii nxt = {-1, 0};

			if(direction[node] == 0){

				nxt = trav(hori[2][Y[node]], node, X[node] + (ll) 2 * dist[pd], 0);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

				nxt = trav(incd[1][X[node] - Y[node]], node, X[node] + dist[pd], 1);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

				nxt = trav(decd[3][X[node] + Y[node]], node, X[node] + dist[pd], 2);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

			}else if(direction[node] == 1){

				nxt = dtrav(vert[3][X[node]], node, Y[node] - (ll) 2 * dist[pd], 0);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

				nxt = trav(decd[2][X[node] + Y[node]], node, X[node] + dist[pd], 1);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

				nxt = dtrav(incd[0][X[node] - Y[node]], node, X[node] - dist[pd], 2);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

			}else if(direction[node] == 2){

				nxt = dtrav(hori[0][Y[node]], node, X[node] - (ll) 2 * dist[pd], 0);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

				nxt = dtrav(incd[3][X[node] - Y[node]], node, X[node] - dist[pd], 1);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

				nxt = dtrav(decd[1][X[node] + Y[node]], node, X[node] - dist[pd], 2);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

			}else if(direction[node] == 3){

				nxt = trav(vert[1][X[node]], node, Y[node] + (ll) 2 * dist[pd], 0);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

				nxt = dtrav(decd[0][X[node] + Y[node]], node, X[node] - dist[pd], 1);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

				nxt = trav(incd[2][X[node] - Y[node]], node, X[node] + dist[pd], 2);
				if(nxt.fi != -1 && dist[nxt.fi] > nxt.se){
					dist[nxt.fi] = nxt.se; pq.push({dist[nxt.fi], nxt.fi});
				}

			}

			colored[node] = true;
			cnt++;
		}
	}

	return cnt;
}

void rotate(){
	for(ll i = 0; i < N; i++){
		swap(X[i], Y[i]);
		Y[i] = -Y[i];
	}
}

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

	cin >> N;
	for(ll i = 0; i < N; i++){
		cin >> X[i] >> Y[i]; X[i] <<= 1, Y[i] <<= 1;
		if(i != 0) X[i] -= X[0], Y[i] -= Y[0];
	}
	X[0] = Y[0] = 0;

	ll ans = 0;
	for(ll i = 0; i < 4; i++){
		ans = max(ans, solve());
		rotate();
	}

	cout << ans << '\n';
}

Compilation message (stderr)

fever.cpp: In function 'void buildEdge(std::vector<std::pair<long long int, long long int> >&, long long int, long long int)':
fever.cpp:25:19: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   25 |   for(ll i = 1; i < v.size(); i++){
      |                 ~~^~~~~~~~~~
fever.cpp: In function 'std::pair<long long int, long long int> trav(std::vector<std::pair<long long int, long long int> >&, long long int, long long int, long long int)':
fever.cpp:43:9: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   43 |  if(idx == v.size()) return make_pair(-1, 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...