一开始以为线段树,后来并不会,其实线段树和平衡树经常能解决类似问题,所以线段树做不了不妨考虑平衡树,写部分分也可以
其实可以用平衡树维护每种颜色的位置,我还想把连续段合成一个点,后来看题解根本不用,直接维护所有出现位置就行,每次启发式合并,用set可水过
然而我迭代器用while写wa了,用for写就过了....
#includeusing 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]); } } }