首页 > 代码库 > [BZOJ 1483]梦幻布丁 线段树

[BZOJ 1483]梦幻布丁 线段树

1483: [HNOI2009]梦幻布丁

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 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

Sample Output

3
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 }

 

[BZOJ 1483]梦幻布丁 线段树