Limite de tempo: C / C ++ 5 segundos, outros idiomas 10 segundos
Limite de espaço: C / C ++ 262144K, outros idiomas 524288K
64bit IO Formato:% lld
Descrição do título
No país de Apolo, o basquete é o esporte mais popular. Existem n jogadores de basquete e m fãs de basquete. Os jogadores de basquete são numerados de 1 a n. Os fãs de basquete são numerados de 1 a m.
Um fã de basquete pode ser um fã de vários jogadores.
O torcedor de basquete i gosta de assistir ao jogo do jogador j se uma das seguintes condições for atendida:
- Fã de basquete i é fã do jogador de basquete j.
- Há um fan i 'e um jogador j', ambos fan i e fan i 'gostam de assistir ao jogo do jogador j', e fan i 'é como assistir ao jogo do jogador j.
O All-Star Game é um jogo de basquete de exibição anual. Você precisa selecionar alguns jogadores para o Jogo All-Star. Um torcedor assistirá ao All-Star Game se quiser assistir ao jogo de um jogador selecionado (ou seja, pelo menos um dos jogadores que o torcedor gosta de assistir foi selecionado). Você precisa decidir o número mínimo de jogadores que deve ser selecionado para o All-Star Game para que todos os fãs de basquete assistam ao jogo.
Inicialmente, alguns jogadores de basquete terão alguns fãs. Existem q mudanças no relacionamento entre jogadores e fãs de basquete.
Após cada mudança de q, imprima um inteiro --- o número mínimo de jogadores que você deve selecionar para fazer com que todos os fãs de basquete assistam ao jogo. Imprima "-1" se for impossível.
Digite a descrição:
The first line contains three integers n, m and q (1≤n,m,q≤2×1051 \le n, m, q \le 2 \times 10^51≤n,m,q≤2×105) - the number of basketball players, the number of basketball fans and the number of changes respectively.
Then n lines follow. The i-th line starts with one integer kik_iki (0≤ki≤m0 \le k_i \le m0≤ki≤m) - the initial number of fans of basketball player i, then contains kik_iki different integers - present the fans of player i.
∑i=1nki≤5×105\sum_{i=1}^n k_i \le 5 \times 10^5∑i=1nki≤5×105.
Then q lines follow. The i-th line contains two integers x and y (1≤x≤m1 \le x \le m1≤x≤m, 1≤y≤n1 \le y \le n1≤y≤n). If fan x is a fan of basketball player y, then fan x will be not a fan of player y, otherwise, fan x will be a fan of player y.
Descrição de saída:
After each change print one integer --- the minimum number of players need to be selected into All-Star Game so that all basketball fans will watch the game. Pritn "-1" if it is impossible.
Exemplo 1
entrar
cópia de
4 4 6
2 1 2
0
2 2 3
1 4
4 2
2 3
2 1
2 2
4 2
4 1
4 4 6
2 1 2
0
2 2 3
1 4
4 2
2 3
2 1
2 2
4 2
4 1
Resultado
2 3 -1 3 4 3
2
3
-1
3
4
3
Se o significado da pergunta não for fácil de explicar, assuma que você já sabe ^ _ ^
solução:
Em primeiro lugar, este é um problema de manutenção dinâmica de blocos conectados , e o problema não é forçado a estar online, então você pode usar a árvore de linha de divisão e conquista de tempo (doravante referida como SJFZ) para resolvê-lo.
SJFZ simplesmente entende que leva o número da consulta como um subscrito e, em seguida, marca o período de tempo em que a borda uv aparece , mescla quando aparece e cancela a subárvore após a recursão ser concluída.
Uma análise mostra que o resultado de cada vez é o número de blocos conectados contendo ventiladores.Se um bloco conectado possuir apenas ventiladores, então a saída é -1, pois nenhum jogador pode fazê-lo ir para o jogo. Portanto, precisamos apenas manter o número de blocos conectados contendo ventiladores enquanto gravamos SJFZ e se há ventiladores sozinhos em um bloco conectado para determinar se a resposta é -1.
Número de blocos conectados de ventiladores : Inicialmente, cada ventilador pode ser marcado. Hav [x] = true significa que o bloco conectado contém ventiladores. Se x for mesclado em y, então hav [y] | = hav [x], ao revogar Basta atualizar e voltar.
Existem ventiladores conectados individualmente em blocos conectados : Basta marcá-los quando os ventiladores conectarem a primeira borda e excluir a última borda.
Se você já aprendeu o SJFZ, basta olhar para as funções mesclar e desfazer As outras são modelos.
Código aceito
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define sc scanf
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))
typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 2e5 + 100;
const int M = 7e5 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }
struct node
{
int u, v, id;
};
struct Node
{
int x, y, l, r;
}st[M];
vector <pir> ver[M * 4];
vector <node> ask[N];
int fz[N * 2], sz[N * 2], n, m, q;
map <pir, int> vis;
map <int, int> fan;
int ans[N], fans, cut, top;
bool ok[N * 2]; // 是否有fans
void Init() {
for (int i = 1; i <= n + m; i++) {
fz[i] = i, sz[i] = 1;
if (i > n)
ok[i] = true;
}
cut = fans = m; // 连通块,单独粉丝
}
int Find(int x) {
while (x != fz[x])
x = fz[x];
return x;
}
void Merge(int x, int y) {
x = Find(x), y = Find(y);
if (x == y) {
st[++top] = { 0, 0 };
return;
}
if (sz[x] > sz[y])
swap(x, y);
fz[x] = y, sz[y] += sz[x];
st[++top] = { x, y, ok[x], ok[y] }; // 保留当前状态
if (ok[x] && ok[y]) // fans合并
cut--;
ok[y] |= ok[x];
if (x > n && sz[x] == 1) // 单独的fans少了
fans--;
}
void Cancle() {
int x = st[top].x, y = st[top].y;
int ok1 = st[top].l, ok2 = st[top].r;
top--;
if (!x || !y)
return;
fz[x] = x, sz[y] -= sz[x];
ok[x] = ok1, ok[y] = ok2;
if (ok1 && ok2) // 都有fans断开
cut++;
if (x > n && sz[x] == 1)
fans++;
}
#define ls (o << 1)
#define rs (ls | 1)
void Update(int o, int L, int R, int l, int r, pir val) {
if (L >= l && R <= r)
ver[o].push_back(val);
else {
int mid = (L + R) >> 1;
if (mid >= l)
Update(ls, L, mid, l, r, val);
if (mid < r)
Update(rs, mid + 1, R, l, r, val);
}
}
void Ask(int o, int L, int R) {
for (auto it : ver[o])
Merge(it.first, it.second);
if (L == R) {
for (auto it : ask[L]) {
int u = it.u, v = it.v;
ans[it.id] = fans ? -1 : cut;
}
}
else {
int mid = (L + R) >> 1;
Ask(ls, L, mid), Ask(rs, mid + 1, R);
}
int sz = SZ(ver[o]);
while (sz--)
Cancle();
}
int main()
{
#ifdef OlaMins
freopen("D:/input.txt", "r", stdin);
//freopen("D:/output.txt", "w", stdout);
#endif
cin >> n >> m >> q;
Init();
for (int i = 1; i <= n; i++) {
int k, u;
sc("%d", &k);
while (k--) {
sc("%d", &u); // fans
u += n;
vis[{u, i}] = 1;
}
}
for (int i = 2; i <= q + 1; i++) {
int x, y;
sc("%d %d", &x, &y); // fans, player
x += n;
if (vis.count({ x, y })) { // 有边,此时要删除
int lst = vis[{x, y}];
vis.erase({ x, y });
Update(1, 1, q + 1, lst, i - 1, { x, y });
}
else // 无边,标记时间
vis[{x, y}] = i;
ask[i].push_back({ x, y, i });
}
for (auto it : vis)
Update(1, 1, q + 1, it.second, q + 1, { it.first.first, it.first.second });
Ask(1, 1, q + 1);
for (int i = 2; i <= q + 1; i++)
printf("%d\n", ans[i]);
return 0; // 改数组大小!!!用pair改宏定义!!!
}