zoukankan      html  css  js  c++  java
  • p3201&bzoj1483 梦幻布丁

    传送门(洛谷)

    传送门(bzoj)

    题目

    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。
    n,m<=1000000

    Output

    针对第二类操作即询问,依次输出当前有多少段颜色.

    Sample Input

    4 3
    1 2 2 1
    2
    1 2 1
    2

    Sample Output

    3
    1

    分析

    用链表将每种颜色的部分连在一起,每次修改利用启发式合并的思想将个数少的颜色合到个数多的颜色,因为这样可能改变颜色对应关系,所有我们用一个数组tr表示这个数所对应的原来的颜色是什么,每一次根据换颜色后是否跟左右颜色一样来更新答案。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<map>
    #include<vector>
    using namespace std;
    int n,m,cnt;
    int col[1000010],c[1000010],size[1000010];
    int ans;
    int be[1000010],head[1000010],tail[1000010],tr[1000010];
    map<int,int>mp;
    int main(){
        int i,j,k;
        cin>>n>>m;
        for(i=1;i<=n;i++){
            cin>>col[i];
            tr[col[i]]=col[i];
            if(col[i]!=col[i-1]){
              c[++cnt]=col[i],size[col[i]]++;
              if(!tail[col[i]])tail[col[i]]=cnt;
              be[cnt]=head[col[i]];
              head[col[i]]=cnt;
            }
        }
        ans=cnt;
        for(i=1;i<=m;i++){
            cin>>k;
            if(k==2)cout<<ans<<endl;
              else {
                  int x,y;
                  cin>>x>>y;
                  if(x==y)continue;
                  if(size[tr[y]]<size[tr[x]])swap(tr[x],tr[y]);
                  x=tr[x];
                  y=tr[y];
                  if(!size[x])continue;
                  for(j=head[x];j;j=be[j]){
                         if(c[j-1]==y){
                        ans--;
                    }
                         if(c[j+1]==y){
                        ans--;
                    }
                  }
                  for(j=head[x];j;j=be[j])
                     c[j]=y;
                  size[y]+=size[x];
                  size[x]=0;
                  be[tail[x]]=head[y];
                  head[y]=head[x];
                  head[x]=tail[x]=0;
              }
        }
        return 0;
    }

  • 相关阅读:
    要加班了!
    项目经理的职责[转]
    用例图(User Case)
    c# 获取收藏夹目录到树型控件
    活动图(Activity Diagram)
    switch case重构事例[转]
    iframe 语法小结
    CSS入门
    Net中几种不同方式的文件下载
    网页效果集合
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9097359.html
Copyright © 2011-2022 走看看