[题解]luogu_P3201_梦幻布丁(启发式合并

一开始以为线段树,后来并不会,其实线段树和平衡树经常能解决类似问题,所以线段树做不了不妨考虑平衡树,写部分分也可以

其实可以用平衡树维护每种颜色的位置,我还想把连续段合成一个点,后来看题解根本不用,直接维护所有出现位置就行,每次启发式合并,用set可水过

然而我迭代器用while写wa了,用for写就过了....

#include
using namespace std;
int n,m,a[1000009],bel[1000009],ans;
set<int>q[1000009];
inline void merge(int x,int y){
    for(set<int>::iterator i=q[x].begin();i!=q[x].end();i++){
        if(a[*i-1]==y)ans--;
        if(a[*i+1]==y)ans--;
        q[y].insert(*i);
    }
    for(set<int>::iterator i=q[x].begin();i!=q[x].end();i++)a[*i]=y;
    q[x].clear();
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(a[i]!=a[i-1])ans++;
        bel[a[i]]=a[i];
        q[a[i]].insert(i);
    }
    for(int i=1,op,x,y;i<=m;i++){
        scanf("%d",&op);
        if(op==2)printf("%d\n",ans);
        else{
            scanf("%d%d",&x,&y);if(x==y)continue;
            if(q[bel[x]].size()>q[bel[y]].size())swap(bel[x],bel[y]);
            merge(bel[x],bel[y]);
        }
    }
}

 

你可能感兴趣的:([题解]luogu_P3201_梦幻布丁(启发式合并)