P3201 [HNOI2009]梦幻布丁  启发式合并_i++

 

P3201 [HNOI2009]梦幻布丁  启发式合并_#include_02

 

 

用启发式合并来做  复杂度为nlong

P3201 [HNOI2009]梦幻布丁  启发式合并_#include_03P3201 [HNOI2009]梦幻布丁  启发式合并_#define_04
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=2e6+10;

int head[N],siz[N],pos,c[N],f[N],st[N],ans,n,m;
int nex[N];
struct Edge{int to,nex;}edge[N<<1];
void add(int a,int b){edge[++pos]=(Edge){b,head[a]};head[a]=pos;}

int Merge(int x,int y)
{
    for(int i=head[x];i;i=edge[i].nex)
    {
        int v=edge[i].to;
        ans-=(y==c[v-1])+(y==c[v+1]);
    }
    for(int i=head[x];i;i=edge[i].nex)c[edge[i].to]=y;
    edge[st[x]].nex=head[y];head[y]=head[x];siz[y]+=siz[x];
    head[x]=siz[x]=st[x]=0;
}
int main()
{
    scanf("%d%d",&n,&m);
    rep(i,1,n)
    {
        scanf("%d",&c[i]);f[c[i]]=c[i];
        ans+=c[i]!=c[i-1];
        if(!head[c[i]])st[c[i]]=pos+1;
        siz[c[i]]++;add(c[i],i);
    }
    while(m--)
    {
        int op;scanf("%d",&op);
        if(op==2)printf("%d\n",ans);
        else
        {
            int x,y;scanf("%d%d",&x,&y);
            if(x==y)continue;
            if(siz[f[x]]>siz[f[y]])swap(f[x],f[y]);
            if(!siz[f[x]])continue;
            Merge(f[x],f[y]);
        }
    }
}
View Code