題目描述
N個布丁擺成一行,進行M次操作,每次將某個顏色的布丁全部變成另一種顏色的,然後再詢問當前一共有多少段顏色。例如顏色分別爲1,2,2,1的四個布丁一共有3段顏色。
輸入格式
第一行給出N,M表示布丁的個數和操作次數;
第二行N個數A1,A2…An表示第i個布丁的顏色
第三行起有M行,對於每個操作,若第一個數字是1表示要對顏色進行改變,其後的兩個整數X,Y表示將所有顏色爲X的變爲Y,X可能等於Y。若第一個數字爲2表示要進行詢問當前有多少段顏色,這時你應該輸出一個整數。
輸出格式
針對第二類操作即詢問,依次輸出當前有多少段顏色。
數據範圍
分析
可以對種顏色開一棵線段樹,範圍爲1~n,表示在區間中爲改顏色的位置,同時線段樹中記錄區間內的段數,爲左+右,若中間都有,則減1。對於顏色變換,直接線段樹合併即可,注意同時維護答案。
注意,對於根節點不能開1000000的數組存,只能用STL map,數組空間開不下,會爆系統棧,然後發生越界現象,然後就有許多莫名奇妙的錯誤,比如Wa,TLE等。
代碼
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <map>
using namespace std;
const int N=100010,M=1000005;
const int LogN=20;
typedef struct SegmentTree {
int l,r,ls,rs,len;
}Segment,SegT;
SegT nd[N*LogN];
int tot;
int st[N*LogN],top;
int n,m,ans,app[N];
map<int,int> rt;
void Clear(int x) {
nd[x].l=nd[x].r=0;
nd[x].len=nd[x].ls=nd[x].rs=0;
}
int New() {
if (top) return Clear(st[top]),st[top--];
else return ++tot;
}
void Pushup(int x) {
int lc=nd[x].l,rc=nd[x].r;
nd[x].len=nd[lc].len+nd[rc].len;
if (nd[lc].rs&&nd[rc].ls) nd[x].len--;
nd[x].ls=nd[lc].ls;
nd[x].rs=nd[rc].rs;
}
void Add(int &rt,int l,int r,int x,int v) {
if (!rt) {
rt=New();
nd[rt].l=nd[rt].r=0;
}
if (l==r) {
nd[rt].len+=v;
nd[rt].ls+=v;
nd[rt].rs+=v;
return;
}
int mid=(l+r)>>1;
if (x<=mid) Add(nd[rt].l,l,mid,x,v);
else Add(nd[rt].r,mid+1,r,x,v);
Pushup(rt);
}
void Recycle(int &y) {
st[++top]=y;
Clear(y);
y=0;
}
void Merge(int l,int r,int&x,int &y) {//x<-y;
if (!y) return;
if (!x) {
x=New();
nd[x]=nd[y];
Recycle(y);
return;
}
if (l==r) {
nd[x].len=nd[y].len;
nd[x].ls=nd[y].ls;
nd[x].rs=nd[y].rs;
Recycle(y);
return;
}
int mid=(l+r)>>1;
Merge(l,mid,nd[x].l,nd[y].l);
Merge(mid+1,r,nd[x].r,nd[y].r);
Recycle(y);
Pushup(x);
}
int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) {
int cl;
scanf("%d",&cl);
app[i]=cl;
Add(rt[cl],1,n,i,1);
}
sort(app+1,app+n+1);
int n_=unique(app+1,app+n+1)-app-1;
for (int i=1;i<=n_;i++)
ans+=nd[rt[app[i]]].len;
for (int i=1;i<=m;i++) {
int op,x,y;
scanf("%d",&op);
if (op==2) printf("%d\n",ans);
else {
scanf("%d%d",&x,&y);//x->y;
if (x==y) continue;
ans-=nd[rt[x]].len;
ans-=nd[rt[y]].len;
Merge(1,n,rt[y],rt[x]);
ans+=nd[rt[y]].len;
}
}
return 0;
}