CodeForces 1303F-Número de componentes (elimine el lado y verifique la colección)

Título

A n ∗ mn * mnorteEl mapa de m , al principio, todos los colores son 0.
Q veces preguntado, cada vez(x, y) (x, y)( x ,y ) la cuadrícula se convierte en el colorccc . Pregunte cuántos bloques conectados del mismo color hay después de cada operación.
Garantíaci c_iCyoSe dan en orden monótono y no decreciente, y aseguran que ci ≤ max (1000, 2 e 6 / (nm)) c_i \ le max (1000,2e6 / (nm))Cyom una x ( 1 0 0 0 ,2 y 6 / ( n m ) )

Ideas para resolver problemas

Las estadísticas se pueden separar según diferentes colores. Luego, modificar el color de una posición equivale a eliminar una posición en un conjunto de colores y agregar una posición en otro conjunto de colores.
Porque garantía ci c_iCyoNo cae, por lo que es imposible unirse después de la operación de eliminación. Por lo tanto, el problema se convierte en el número de bloques conectados después de eliminar algunos bordes de un gráfico. Este es el problema clásico de la búsqueda de sindicatos: eliminar bordes y buscar. Puede pensar en eliminar bordes en orden como agregar bordes en orden inverso.
Debido a que la eliminación de bordes y conjuntos de búsqueda necesitan agregar bordes que no se han eliminado, agregamos los colores correspondientes a la secuencia de eliminación en el último gráfico guardado y luego dejamos que no participen en las estadísticas de respuesta, de modo que al contar las respuestas Estas posiciones no eliminadas ya están en la imagen.

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define lowbit(x) ((x)&(-(x)))
#define mid ((l+r)>>1)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define fors(i, a, b) for(int i = (a); i < (b); ++i)
#define P pair<int,int>
using namespace std;
int n, m, q;
const int maxn = 2e5 + 50;
int rk[maxn], fa[maxn];
int fnd(int x){
    
    return (x == fa[x])?x:fa[x] = fnd(fa[x]);}
int link(int u, int v){
    
    
    u = fnd(u); v = fnd(v);
    if(u == v) return 0;
    if(rk[u] < rk[v]) swap(u, v);
    fa[v] = u; if(rk[u] == rk[v]) rk[u]++;
    return 1;
}
vector<int> g[maxn];
int a[maxn];
void init(){
    
    
    scanf("%d%d%d", &n, &m, &q);
    fors(i, 0, n*m) fa[i] = i;
    fors(i, 0, n) fors(j, 0, m-1) {
    
    
        int u = i*m+j, v = i*m+j+1;
        g[u].pb(v); g[v].pb(u);
    }
    fors(j, 0, m) fors(i, 0, n-1){
    
    
        int u = i*m+j, v = (i+1)*m+j;
        g[u].pb(v); g[v].pb(u);
    }
}
vector<P> add[maxn*10], del[maxn*10];
int d[maxn*10];
void work(vector<P> &c, int op){
    
    
    fors(i, 0, n) fors(j, 0, m) a[i*m+j] = 0, fa[i*m+j] = i*m+j, rk[i*m+j] = 1;

    for(auto t: c){
    
    
        int u = t.first, id = t.second;
        int cur = 1; a[u] = 1;
        for(int v: g[u]){
    
    
            if(a[v]) cur -= link(u, v);
        }
        d[id] += cur*op;
    }
}
void sol(){
    
    
    int mx = 1;
    for(int i = 0; i < q; ++i){
    
    
        int x, y, c; scanf("%d%d%d", &x, &y, &c);x--;y--;
        int u = x*m+y;
        if(c == a[u]) continue;
        mx = c+1;
        add[c].pb(P(u, i));
        del[a[u]].pb(P(u, i));
        a[u] = c;
    }
    fors(i, 0, n*m) del[a[i]].pb(P(i, q));
    fors(i, 0, mx) reverse(del[i].begin(), del[i].end());

    fors(i, 0, mx) work(add[i], 1);
    fors(i, 0, mx) work(del[i], -1);

    int ans = 1;
    fors(i, 0, q) ans += d[i], printf("%d\n", ans);
}
int main()
{
    
    
    init();
    sol();
}

Supongo que te gusta

Origin blog.csdn.net/qq_43202683/article/details/104321440
Recomendado
Clasificación