[BZOJ 1483]梦幻布丁 线段树
1483: [HNOI2009]梦幻布丁
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2813 Solved: 1113
[Submit][Status][Discuss]
Description
N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色.
Input
第一行给出N,M表示布丁的个数和好友的操作次数. 第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y. 若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个整数.
Output
针对第二类操作即询问,依次输出当前有多少段颜色.
Sample Input
4 3
1 2 2 1
2
1 2 1
2
1 2 2 1
2
1 2 1
2
Sample Output
3
1
1
HINT
1<=n,m<=100,000; 0<Ai,x,y<1,000,000
一棵线段树可以解决的题,线段树每个节点存三个权值l r date ,代表该节点所代表线段的最左边的颜色 ,最右边的颜色以及颜色总的种类数。记录l , r 是为了求date,防止因左儿子的最右端和右儿子的最左端颜色相同导致date比实际的要大。。。
1 #include <cmath> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 8 using namespace std; 9 10 const int maxn=1e5+200; 11 const int maxtype=1e6; 12 13 #define LL long long 14 #define lson rt<<1,l,mid 15 #define rson rt<<1|1,mid+1,r 16 17 struct Node{ 18 int l,r,date; 19 }a[maxn<<2]; 20 vector<int> g[maxtype+200]; 21 int n,m,mp[maxtype+200]; 22 bool us[maxtype+200]; 23 24 void Init(); 25 void pushup(int rt){ 26 a[rt].l=a[rt<<1].l,a[rt].r=a[rt<<1|1].r; 27 if(a[rt<<1].r==a[rt<<1|1].l)a[rt].date=a[rt<<1].date+a[rt<<1|1].date-1; 28 else a[rt].date=a[rt<<1].date+a[rt<<1|1].date; 29 } 30 void Build(int rt,int l,int r){ 31 if(l==r){ 32 int z;scanf("%d",&z); 33 mp[z]=z;us[z]=true;g[z].push_back(l); 34 a[rt].l=a[rt].r=z;a[rt].date=1; 35 return; 36 } 37 int mid=(l+r)>>1; 38 Build(lson);Build(rson); 39 pushup(rt); 40 } 41 void Insert(int x,int z,int rt,int l,int r){ 42 if(l==r){ 43 a[rt].l=a[rt].r=z;a[rt].date=1; 44 return; 45 } 46 int mid=(l+r)>>1; 47 if(x<=mid)Insert(x,z,lson); 48 else Insert(x,z,rson); 49 pushup(rt); 50 } 51 int main(){ 52 Init(); 53 getchar();getchar(); 54 return 0; 55 } 56 void Init(){ 57 scanf("%d%d",&n,&m); 58 Build(1,1,n); 59 for(int i=1;i<=m;i++){ 60 int type;scanf("%d",&type); 61 if(type==2)printf("%d\n",a[1].date); 62 else { 63 int x,y;scanf("%d%d",&x,&y); 64 if(!us[x]){us[x]=true;mp[x]=x;} 65 if(!us[y]){us[y]=true;mp[y]=y;} 66 if(x==y)continue; 67 if(g[mp[x]].size()>g[mp[y]].size())swap(mp[x],mp[y]); 68 for(int j=0;j<g[mp[x]].size();j++){ 69 int pos=g[mp[x]][j]; 70 Insert(pos,mp[y],1,1,n); 71 g[mp[y]].push_back(pos); 72 } 73 g[mp[x]].clear(); 74 } 75 } 76 }