zoukankan      html  css  js  c++  java
  • 【链表+启发式合并】Bzoj1483 [HNOI2009] 梦幻布丁

    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
     

    题解

    用链表来更好的遍历每种颜色 暴力遍历算对答案的贡献
    合并时用启发式合并 就是如果s[b]<s[a] 就把b和入a 但是把a和b真实对应的颜色改一下(很常用的技巧)
     
    那么对于最不好的情况 也就是每次s[b]=s[a]
    合并时 s扩大logn次 如果把同一个s级别的一起看 每次O(n) 所以最坏时间复杂度O(nlogn)
    虽然这道题不用启发式合并速度也差不多(但就要注意b为空的情况了 启发式合并可以直接避免)
     
    再次记一下合并链表步骤(合a入b)
    next[b尾]=a首;b首=a首;清空a;
     

    代码

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5,M=1e6+5;
    
    int c[N],next[N],head[M],last[M],p[M],s[M];
    int n,m,ans;
    
    int solve(int a,int b){
        s[b]+=s[a];s[a]=0;
        
        for(int i=last[a];i;i=next[i]){
            if(c[i-1]==b) ans--;
            if(c[i+1]==b) ans--;
        }
        for(int i=last[a];i;i=next[i]) c[i]=b;
        
        next[head[b]]=last[a];
        head[b]=head[a];
        last[a]=head[a]=0;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        
        for(int i=1;i<=n;i++){
            scanf("%d",&c[i]);
            p[c[i]]=c[i];
            s[c[i]]++;
            if(c[i]!=c[i-1]) ans++;
            if(!last[c[i]]) head[c[i]]=i;
            next[i]=last[c[i]];
            last[c[i]]=i;
        }
        
        int x,a,b;
        for(int i=1;i<=m;i++){
            scanf("%d",&x);
            if(x==1){
                scanf("%d%d",&a,&b);
                if(a==b) continue;
                if(s[p[a]]>s[p[b]]) swap(p[a],p[b]);
                a=p[a];b=p[b];
                if(!s[a]) continue;
                solve(a,b);
            }
            else printf("%d
    ",ans);
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    图片上传-下载-删除等图片管理的若干经验总结3-单一业务场景的完整解决方案
    图片上传-下载-删除等图片管理的若干经验总结2
    HDU 1195 Open the Lock
    HDU 1690 Bus System
    HDU 2647 Reward
    HDU 2680 Choose the best route
    HDU 1596 find the safest road
    POJ 1904 King's Quest
    CDOJ 889 Battle for Silver
    CDOJ 888 Absurdistan Roads
  • 原文地址:https://www.cnblogs.com/xkui/p/4535512.html
Copyright © 2011-2022 走看看