[HNOI2009]夢幻布丁
阿新 • • 發佈:2018-10-31
[HNOI2009]夢幻布丁
給每個顏色的點掛個鏈.按size啟發式暴力合併.
如果一個聯通的色塊左邊或者右邊等於要變的顏色,那麼色塊總數減一.這樣維護答案就好了.
#include<bits/stdc++.h> using namespace std; #define maxn 1000005 int head[maxn],nxt[maxn],n,m,ans,cor[maxn],sz[maxn],ori[maxn]; void merge(int &x,int &y) { if(x==y)return; if(sz[x]>sz[y])swap(x,y); for(int i=head[x];i;i=nxt[i]) { ans-=(cor[i-1]==y)+(cor[i+1]==y); if(!nxt[i]){nxt[i]=head[y],head[y]=head[x];break;} } for(int i=head[x];i;i=nxt[i])cor[i]=y; sz[y]+=sz[x];sz[x]=0;head[x]=0; } int main() { cin>>n>>m;int ty,x,y; for(int i=1;i<=n;i++) scanf("%d",&cor[i]),nxt[i]=head[cor[i]],head[cor[i]]=i,sz[cor[i]]++; for(int i=1;i<=maxn-5;i++)ori[i]=i; ans=1;for(int i=2;i<=n;i++)if(cor[i]!=cor[i-1])ans++; for(int i=1;i<=m;i++) { scanf("%d",&ty); if(ty==1)scanf("%d%d",&x,&y),merge(ori[x],ori[y]); else printf("%d\n",ans); } return 0; }