結果
| 問題 |
No.2290 UnUnion Find
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-05-05 22:28:02 |
| 言語 | D (dmd 2.109.1) |
| 結果 |
AC
|
| 実行時間 | 344 ms / 2,000 ms |
| コード長 | 5,646 bytes |
| コンパイル時間 | 3,434 ms |
| コンパイル使用メモリ | 242,484 KB |
| 実行使用メモリ | 36,268 KB |
| 最終ジャッジ日時 | 2024-06-22 17:50:01 |
| 合計ジャッジ時間 | 20,918 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 46 |
ソースコード
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, Q;
cin(N, Q);
auto dsu = new Dsu(N);
auto set = new RedBlackTree!long();
foreach (i; 0 .. N) {
set.insert(i);
}
foreach (q; 0 .. Q) {
int k;
cin(k);
if (k == 1) {
int u, v;
cin(u, v);
u--;
v--;
if (dsu.same(u, v))
continue;
int G = dsu.leader(u) ^ dsu.leader(v);
G ^= dsu.merge(u, v);
set.removeKey(G);
} else {
int v;
cin(v);
v--;
v = dsu.leader(v);
auto it = set.upperBound(v);
if (!it.empty()) {
(it.front() + 1).writeln;
} else {
it = set.lowerBound(v);
if (it.empty()) {
writeln(-1);
} else {
(it.front() + 1).writeln;
}
}
}
}
}