CF571D Campus

Link
In fact, we are maintaining the two forests.
When you merge two points, we consider a new point, store information with this new point, and then the root of the tree where the need to merge the two points connected to this point.
If only the University operation, we can modify each to the root of a tree hit, it is a point of asking the right value to the root path and that this can be achieved with the right to disjoint-set.
Now add the operations of the army, if we know the last time a point is covered, then we can operate off-line at the University of + differential resolved. This can be used similarly weighted disjoint-set to achieve.

#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]);
}

Guess you like

Origin www.cnblogs.com/cjoierShiina-Mashiro/p/12450876.html