제출 #568047

#제출 시각아이디문제언어결과실행 시간메모리
568047ZaniteSwapping Cities (APIO20_swap)C++17
100 / 100
1190 ms50868 KiB
// You can't change other people; you can only change yourself.

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#include "swap.h"

// Pragmas
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

// Namespaces
#define yume using
#define wo namespace
#define kanaeyo std
#define nazotte __gnu_pbds
yume wo kanaeyo;
yume wo nazotte;

// Data types
using i8	= __int128;
using ll	= long long;
using si	= short int;
using ld	= long double;

// Pairs
using pi8	= pair<i8, i8>;
using pll	= pair<ll, ll>;
using pii	= pair<int, int>;
using psi	= pair<si, si>;
using pld	= pair<ld, ld>;
#define fi first
#define se second

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

// Quick macro functions
#define sqr(x) ((x)*(x))
#define pow2(x) (1ll << (x))
#define debug(x) cout << #x << " = " << (x) << '\n'
#define debugV(x, a) cout << #x << "[" << (a) << "] = " << (x[a]) << '\n'

// Check min and max
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
 
// Modular arithmetic
template<typename T> void maddto(T &a, T b, T mod) {a += b; a %= mod;}
template<typename T> void msubto(T &a, T b, T mod) {a -= b; while (a < 0) a += mod; a %= mod;}
template<typename T> void mmulto(T &a, T b, T mod) {a *= b; a %= mod;}
 
template<typename T> T madd(T a, T b, T mod) {a += b; a %= mod; return a;}
template<typename T> T msub(T a, T b, T mod) {a -= b; while (a < 0) a += mod; return a;}
template<typename T> T mmul(T a, T b, T mod) {a *= b; a %= mod; return a;}

// Constants
const ll ModA	= 998244353;
const ll ModC	= 1e9 + 7;
const ll INF	= 1e18;
const ll iINF	= 1e9;
const ld EPS	= 1e-9;
const ld iEPS	= 1e-6;

struct OnlineDSU {
	int n;
	vector<vector<pii>> par, sz, degree, maxdegree, edgecount;

	OnlineDSU(int _n) {
		n = _n;
		for (int i = 0; i < n; i++) {
			par.push_back({{0, i}});
		}
		sz.assign(n, {{0, 1}});
		degree.assign(n, {{0, 0}});
		maxdegree.assign(n, {{0, 0}});
		edgecount.assign(n, {{0, 0}});
	}

	void insert(vector<pii> &v, int val, int t) {
		if (v.back().se == val) {return;}
		if (v.back().fi == t) {
			v.back().se = val;
		} else {
			v.push_back({t, val});
		}
	}

	int query(vector<pii> &v, int t) {
		pii search = {t+1, -iINF};
		auto it = upper_bound(v.begin(), v.end(), search);
		it--;
		return it->second;
	}

	int parent_latest(int x) {return par[x].back().se;}
	int size_latest(int x) {return sz[x].back().se;}
	int degree_latest(int x) {return degree[x].back().se;}
	int maxdegree_latest(int x) {return maxdegree[x].back().se;}
	int edgecount_latest(int x) {return edgecount[x].back().se;}

	int get_degree(int x, int t) {return query(degree[x], t);}
	int get_maxdegree(int x, int t) {return query(maxdegree[x], t);}
	int get_edgecount(int x, int t) {return query(edgecount[x], t);}
	int get_size(int x, int t) {return query(sz[x], t);}

	int rep_latest(int x, int t) {
		if (x == parent_latest(x)) {return x;}
		insert(par[x], rep_latest(parent_latest(x), t), t);
		return parent_latest(x);
	}

	int rep(int x, int t) {
		int p = query(par[x], t);
		if (x == p) {return x;}
		return rep(p, t);
	}

	void join_latest(int u, int v, int t) {
		insert(degree[u], degree_latest(u)+1, t);
		insert(degree[v], degree_latest(v)+1, t);

		int x = rep_latest(u, t), y = rep_latest(v, t);
		if (x != y) {
			if (size_latest(x) < size_latest(y)) {swap(x, y);}

			insert(par[y], x, t);
			insert(sz[x], size_latest(x) + size_latest(y), t);

			int mx = maxdegree_latest(x), my = maxdegree_latest(y);
			insert(maxdegree[x], max(max(mx, my), max(degree_latest(u), degree_latest(v))), t);

			int ex = edgecount_latest(x), ey = edgecount_latest(y);
			insert(edgecount[x], ex+ey+1, t);
		} else {
			insert(maxdegree[x], max(maxdegree_latest(x), max(degree_latest(u), degree_latest(v))), t);
			int e = edgecount_latest(x);
			insert(edgecount[x], e+1, t);
		}
	}

	bool check(int u, int v, int t) {
		int x = rep(u, t), y = rep(v, t);
		return (x == y);
	}
};

void print(vector<vector<pii>> &v) {
	for (int i = 0; i < v.size(); i++) {
		cout << i << ": ";
		for (auto j : v[i]) {
			cout << "{" << j.fi << ", " << j.se << "} ";
		}
		cout << '\n';
	}
	cout << '\n';
}

using Edge	= pair<int, pii>;

OnlineDSU *D;

void init(int N, int M, vector<int> U, vector<int> V, vector<int> W) {
	vector<Edge> E;
	for (int i = 0; i < M; i++) {
		E.push_back({W[i], {U[i], V[i]}});
	}
	sort(E.begin(), E.end());

	D = new OnlineDSU(N);
	for (auto x : E) {
		D->join_latest(x.se.fi, x.se.se, x.fi);
		//printf("%d: %d %d\n", x.fi, x.se.fi, x.se.se);
	}

	/*
	cout << "par\n";
	print(D->par);
	cout << "sz\n";
	print(D->sz);
	cout << "degree\n";
	print(D->degree);
	cout << "maxdegree\n";
	print(D->maxdegree);
	cout << "edgecount\n";
	print(D->edgecount);
	*/
}

const int MAX = 1e9;

int getMinimumFuelCapacity(int X, int Y) {
	int L = 1, R = MAX, ans = -1;
	while (L <= R) {
		int M = (L + R) >> 1;

		bool pos = 1;
		if (!D->check(X, Y, M)) {
			pos = 0;
		} else {
			int R = D->rep(X, M);
			if (D->get_maxdegree(R, M) > 2 || (D->get_size(R, M) == D->get_edgecount(R, M))) {
				pos = 1;
			} else {
				pos = 0;
			}
		}

		if (pos) {
			R = M - 1;
			ans = M;
		} else {
			L = M + 1;
		}
	}
	return ans;
}

//int main() {}

컴파일 시 표준 에러 (stderr) 메시지

swap.cpp: In function 'void print(std::vector<std::vector<std::pair<int, int> > >&)':
swap.cpp:152:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<std::pair<int, int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  152 |  for (int i = 0; i < v.size(); i++) {
      |                  ~~^~~~~~~~~~
#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...