З'єднання та роз'єднання#4140

З'єднання та роз'єднання

2 секунди
256 мегабайтів
Легка

Ви коли-небудь чули про обхід в глибину? Наприклад, використовуючи цей алгоритм, ви можете перевірити, чи є граф зв'язним, за час . Ви можете навіть порахувати кількість компонент зв'язності за цей же час.

А ви коли-небудь чули про систему множин, які не перетинаються? Використовуючи цю структуру, ви можете швидко опрацьовувати запити "Додати ребро в граф" та "Порахувати кількість компонент зв'язності у графі".

А ви коли-небудь чули про динамічну задачу зв'язності? У цій задачі вам потрібно опрацьовувати три типи запитів:

  1. Додати ребро в граф.

  2. Видалити ребро з графа.

  3. Порахувати кількість компонент зв'язності у графі.

Вхідні дані

Спочатку граф порожній.

У першому рядку знаходяться два цілих числа та — кількість вершин та кількість запитів відповідно (1 \leq N \leq 300000, 0 \leq K \leq 300000). Наступні рядків містять запити, по одному у рядку. Є три типи запитів:

  1. + : Додати ребро між вершинами та . Гарантується, що такого ребра немає.

  2. - : Видалити ребро між та . Гарантується, що таке ребро є.

  3. ?: Порахувати кількість компонент зв'язності у графі.

Вершини пронумеровано цілими числами від до . У всіх запитах u \neq v. Граф вважається неорієнтованим.

Вихідні дані

Для кожного запиту типу "?", виведіть кількість компонент зв'язності у момент запиту.

Приклади

Приклад 1

Loading
Loading