Campus CF571D

Enlace
De hecho, estamos manteniendo los dos bosques.
Cuando se fusionan dos puntos, que consideramos un nuevo punto de información, tienda con este nuevo punto, y luego la raíz del árbol, donde la necesidad de fusionar los dos puntos conectados a este punto.
Si sólo el funcionamiento de la Universidad, que puede modificar cada a la raíz de un árbol de golpe, es un punto de pedir el valor correcto a la ruta raíz y que esto se puede lograr con el derecho a disjuntos-set.
Ahora agregue las operaciones del ejército, si conocemos la última vez que se cubrió un punto, entonces podemos operar fuera de línea en la Universidad de + diferencial resuelto. Esto puede ser usado de manera similar ponderada disjuntos-set de lograr.

#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<numeric>
#include<algorithm>
using i64=long long;
const int N=1000007;
int fa[N],vis[N],size[N];i64 tag[N],ans[N];
struct node{int o,t,x,y,id;};std::vector<node>vec;
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
char get(){char c=getchar();while(!isupper(c))c=getchar();return c;}
int find(int x,int f)
{
    if(fa[fa[x]]==fa[x]) return fa[x];
    int y=find(fa[x],f); return tag[x]=f? std::max(tag[x],tag[fa[x]]):tag[x]+tag[fa[x]],fa[x]=y;
}
int main()
{
    int n=read(),m=read(),cnt=n;
    std::iota(fa+1,fa+n+n+1,1);
    for(int i=1,x,y;i<=m;++i)
    switch(get())
    {
    case 'U':x=read(),y=read(),vec.push_back({0,i,x,y,0});break;
    case 'M':x=read(),y=read(),++cnt,fa[find(x,1)]=fa[find(y,1)]=cnt;break;
    case 'A':vec.push_back({-1,i,read(),0,0});break;
    case 'Z':tag[find(read(),1)]=i;break;
    case 'Q':
        x=read(),vis[i]=1,vec.push_back({1,i,x,1,i}),y=find(x,1);
        if(tag[x]||tag[y]) vec.push_back({1,(int)std::max(tag[x],tag[y]),x,-1,i});;
        break;
    }
    std::sort(vec.begin(),vec.end(),[](const node&a,const node&b){return a.t<b.t;}),std::iota(fa+1,fa+n+n+1,1),std::fill(size+1,size+n+n+1,1),memset(tag+1,0,n<<4),cnt=n;
    for(auto t:vec)
    switch(t.o)
    {
    case -1:tag[find(t.x,0)]+=size[find(t.x,0)];break;
    case 0:t.x=find(t.x,0),t.y=find(t.y,0),++cnt,size[cnt]=size[t.x]+size[t.y],fa[t.x]=fa[t.y]=cnt;break;
    case 1:find(t.x,0),ans[t.id]+=t.y*(tag[t.x]+(fa[t.x]==t.x? 0:tag[fa[t.x]]));
    }
    for(int i=1;i<=m;++i) if(vis[i]) printf("%lld\n",ans[i]);
}

Supongo que te gusta

Origin www.cnblogs.com/cjoierShiina-Mashiro/p/12450876.html
Recomendado
Clasificación