結果
| 問題 |
No.2289 順列ソート
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-05-08 17:03:03 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 2 ms / 2,000 ms |
| コード長 | 3,024 bytes |
| コンパイル時間 | 1,711 ms |
| コンパイル使用メモリ | 176,504 KB |
| 実行使用メモリ | 6,820 KB |
| 最終ジャッジ日時 | 2024-11-25 08:19:45 |
| 合計ジャッジ時間 | 2,775 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 21 |
ソースコード
/* ------------------------------ include ------------------------------ */
#include <bits/stdc++.h>
// #include <atcoder/modint>
// #include <boost/multiprecision/cpp_int.hpp>
/* ------------------------------ using ------------------------------ */
using namespace std;
// using namespace atcoder;
// using namespace boost::multiprecision;
/* ------------------------------ define ------------------------------ */
#define all(container) (container).begin(), (container).end()
#define ctoi(char) int(char) - 48
#define rep(i,n) for (int i = 0; (i) < (int)(n); ++ (i))
#define rep3(i,m,n) for (int i = (m); (i) < (int)(n); ++ (i))
#define per(i,n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))
#define per3(i,m,n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))
// #define int long long
/* ------------------------------ function ------------------------------*/
template<typename T> inline bool chmax(T &a, T b) { return ((a < b) ? (a = b, true) : (false)); }
template<typename T> inline bool chmin(T &a, T b) { return ((a > b) ? (a = b, true) : (false)); }
template<typename T> T lcm(T a, T b) {return a / gcd(a, b) * b;}
/* ------------------------------ const ------------------------------ */
constexpr double PI = acos(-1.0);
constexpr int dx[4] = {1, 0, -1, 0};
constexpr int dy[4] = {0, 1, 0, -1};
constexpr long long MOD = 1000000007;
constexpr long long _MOD = 998244353;
/* ------------------------------ code ------------------------------ */
class UnionFind
{
public:
vector<long long> parent;
vector<long long> set_size;
// constructor
UnionFind (long long n): parent(n), set_size(n, 1LL)
{
for (long long i = 0; i < n; ++i) parent[i] = i;
}
void init(long long n)
{
parent.resize(n);
set_size.assign(n, 1LL);
for (long long i = 0; i < n; ++i) parent[i] = i;
}
long long root (long long x) // find (path halving)
{
while (parent[x] != x)
{
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
bool merge (long long x, long long y) // union by size
{
long long rx = root(x);
long long ry = root(y);
if (rx == ry) return false;
else if (set_size[rx] < set_size[ry]) swap(rx, ry); // root(y) のほうがデカいときも merge できるように逆にする
// Operations
parent[ry] = rx;
set_size[rx] += set_size[ry];
return true;
}
bool same (long long x, long long y)
{
return root(x) == root(y);
}
long long size(long long x)
{
return set_size[root(x)];
}
};
signed main ()
{
cin.tie(nullptr);
ios_base::sync_with_stdio(false);
int n; cin >> n;
vector<int> p(n); rep(i, n) cin >> p[i];
UnionFind tree(n);
for (int i = 0; i < n; ++i)
{
p[i]--;
tree.merge(p[i], i);
}
set<int> checked;
int answer = 0;
for (int i = 0; i < n; ++i)
{
if (checked.find(tree.root(i)) == checked.end())
{
checked.emplace(tree.root(i));
answer += tree.size(i) - 1;
}
}
cout << answer << endl;
return 0;
}