結果
| 問題 |
No.2289 順列ソート
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-05-05 22:16:13 |
| 言語 | D (dmd 2.109.1) |
| 結果 |
AC
|
| 実行時間 | 2 ms / 2,000 ms |
| コード長 | 4,919 bytes |
| コンパイル時間 | 4,670 ms |
| コンパイル使用メモリ | 228,688 KB |
| 実行使用メモリ | 6,944 KB |
| 最終ジャッジ日時 | 2024-06-22 17:49:17 |
| 合計ジャッジ時間 | 4,620 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 21 |
ソースコード
public import std;
DList!string scan_buffer;
DList!char char_buffer;
static this() {
scan_buffer = DList!(string)();
char_buffer = DList!(char)();
}
void cin()() {
}
void cin(T, A...)(ref T a, ref A tail) {
import std.traits : isArray;
static if (typeof(a).stringof == "string") {
if (!char_buffer.empty) {
a = char_buffer.array.map!(x => x.to!string).join();
char_buffer.clear();
} else {
while (scan_buffer.empty) {
foreach (t; readln.split) {
if (t.length == 0) {
continue;
}
scan_buffer.insert(t);
}
}
auto token = scan_buffer.front;
scan_buffer.removeFront();
a = token;
}
} else static if (typeof(a).stringof == "char") {
if (!char_buffer.empty) {
a = char_buffer.front();
char_buffer.removeFront();
} else {
while (scan_buffer.empty) {
foreach (t; readln.split) {
if (t.length == 0) {
continue;
}
scan_buffer.insert(t);
}
}
auto token = scan_buffer.front;
scan_buffer.removeFront();
a = token[0];
if (token.length > 1) {
foreach (c; token[1 .. $]) {
char_buffer.insertBack(c);
}
}
}
} else static if (typeof(a).stringof == "char[]") {
if (a.length == 0) {
string token;
cin(token);
foreach (c; token) {
a ~= c;
}
} else {
foreach (ref v; a) {
cin(v);
}
}
} else static if (isArray!(typeof(a))) {
foreach (ref v; a) {
cin(v);
}
} else static if (isTuple!(typeof(a))) {
foreach (i, _; a) {
cin(a[i]);
}
} else {
if (!char_buffer.empty) {
writeln(char_buffer.array.map!(x => x.to!string));
a = char_buffer.array.map!(x => x.to!string).join().to!T;
char_buffer.clear();
} else {
while (scan_buffer.empty) {
foreach (t; readln.split) {
if (t.length == 0) {
continue;
}
scan_buffer.insert(t);
}
}
auto token = scan_buffer.front;
scan_buffer.removeFront();
a = token.to!T;
}
}
cin(tail);
}
bool chmin(T)(ref T a, T b) {
if (a > b) {
a = b;
return true;
}
return false;
}
bool chmax(T)(ref T a, T b) {
if (a < b) {
a = b;
return true;
}
return false;
}
alias PQueue(T = long, alias less = "a<b") = BinaryHeap!(Array!T, less);
class Dsu {
public:
this(long n) @safe nothrow {
_n = cast(int) n, parent_or_size = new int[](n);
parent_or_size[] = -1;
}
int merge(long a, long b) @safe nothrow @nogc {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
int x = leader(a), y = leader(b);
if (x == y)
return x;
if (-parent_or_size[x] < -parent_or_size[y]) {
auto tmp = x;
x = y;
y = tmp;
}
parent_or_size[x] += parent_or_size[y];
parent_or_size[y] = x;
return x;
}
bool same(long a, long b) @safe nothrow @nogc {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
return leader(a) == leader(b);
}
int leader(long a) @safe nothrow @nogc {
assert(0 <= a && a < _n);
if (parent_or_size[a] < 0)
return cast(int) a;
return parent_or_size[a] = leader(parent_or_size[a]);
}
int size(long a) @safe nothrow @nogc {
assert(0 <= a && a < _n);
return -parent_or_size[leader(a)];
}
int[][] groups() @safe nothrow {
auto leader_buf = new int[](_n), group_size = new int[](_n);
foreach (i; 0 .. _n) {
leader_buf[i] = leader(i);
group_size[leader_buf[i]]++;
}
auto result = new int[][](_n);
foreach (i; 0 .. _n)
result[i].reserve(group_size[i]);
foreach (i; 0 .. _n)
result[leader_buf[i]] ~= i;
int[][] filtered;
foreach (r; result)
if (r.length != 0)
filtered ~= r;
return filtered;
}
private:
int _n;
int[] parent_or_size;
}
void main() {
int N;
cin(N);
auto P = new int[N];
cin(P);
auto dsu = new Dsu(N);
foreach (i, p; P) {
dsu.merge(i, p - 1);
}
auto gr = dsu.groups();
gr.map!(g => (g.length - 1)).sum.writeln;
}