zoukankan      html  css  js  c++  java
  • 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
    ",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 }
  • 相关阅读:
    PHP-Resque 简介
    基于Redis的消息队列php-resque
    sms_queue 短信队列
    那些最好的轮子
    Sphinx高亮显示关键字
    atitit.系统托盘图标的设计java swing c# .net c++ js
    atitit.验证码识别step4--------图形二值化 灰度化
    atitit.验证码识别step3----去除边框---- 图像处理类库 attilax总结java版本
    atitit.验证码识别step2------剪贴板ClipBoard copy image图像 attilax总结
    atitit.loading的设计与实现控件选型attilax 总结
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6189093.html
Copyright © 2011-2022 走看看