Bzoj1483 [HNOI2009]梦幻布丁

Posted SilverNebula

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj1483 [HNOI2009]梦幻布丁相关的知识,希望对你有一定的参考价值。

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 2655  Solved: 1063

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表示要进行询问当前有多少段颜色,这时你应该输出一个整数. 0

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

Source

 

看到数据范围比较怂,然而看到题解都是用挺暴力的方法刚过去的。想了想好像有点道理。

 

链表+启发式合并

 

用链表存储每种颜色的所有布丁的位置,每次修改时,合并链表和颜色标记,记录链表长度,暴力修改长度较小的那个链表。

然而写挂了。向题解低头之后发现没有记录布丁原来的颜色,导致染色出了偏差。

 

↓注意37和38行的语句差别。要根据原色判断是否该染。

 1 #include<algorithm>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<cstdio>
 5 using namespace std;
 6 const int mxn=2000100;
 7 int read(){
 8     int x=0,f=1;char ch=getchar();
 9     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}
10     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}
11     return x*f;
12 }
13 int n,m;
14 int hd[mxn],nxt[mxn],cnt[mxn];
15 int now[mxn];
16 int co[mxn];
17 int main()
18 {
19     int i,j;
20     n=read();m=read();
21     int ans=0;
22     for(i=1;i<=n;i++){
23         co[i]=read();
24         cnt[co[i]]++;
25         nxt[i]=hd[co[i]];
26         now[co[i]]=co[i];
27         hd[co[i]]=i;
28         if(co[i]!=co[i-1])ans++;
29     }
30     int x,y;
31     for(i=1;i<=m;i++){
32         x=read();
33         if(x==2){printf("%d\n",ans);}
34         else{
35             x=read();y=read();
36             if(x==y)continue;
37 //          if(cnt[x]>cnt[y])swap(x,y);
38             if(cnt[now[x]]>cnt[now[y]])swap(now[x],now[y]);
39             x=now[x];y=now[y];//原色 
40             if(!cnt[x])continue;
41             int last=0;
42             for(j=hd[x];j;j=nxt[j]){
43                 if(co[j-1]==y)ans--;
44                 if(co[j+1]==y)ans--;
45                 last=j;
46             }
47             for(j=hd[x];j;j=nxt[j]){
48                 co[j]=y;
49             }
50             nxt[last]=hd[y];
51             hd[y]=hd[x];
52             hd[x]=0;
53             cnt[y]+=cnt[x];
54             cnt[x]=0;
55         }
56     }
57     return 0;
58 }

 

以上是关于Bzoj1483 [HNOI2009]梦幻布丁的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1483[HNOI2009]梦幻布丁 set

bzoj 1483: [HNOI2009]梦幻布丁

BZOJ1483[HNOI2009]梦幻布丁 链表+启发式合并

bzoj 1483: [HNOI2009]梦幻布丁 启发式合并vector

Bzoj1483 [HNOI2009]梦幻布丁

BZOJ 1483:[HNOI2009]梦幻布丁(链表+启发式合并)