• [bzoj1483]:[HNOI2009]梦幻布丁


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色.

    n,m<=10^5 ai<=10^6

    第一眼觉得可以平衡树+启发式合并

    但是想了想直接启发式合并就行了  用链表链起来即可。

    复杂度最坏nlogn

    #include<iostream>
    #include<cstdio>
    #define rint register int
    #define MN 100000
    using namespace std;
    inline int read()
    {
        int x = 0; char ch = getchar();
        while(ch < '0' || ch > '9')  ch = getchar();
        while(ch >= '0' && ch <= '9')x = x * 10 + ch - '0',ch = getchar();
        return x;
    }
    
    int n,m,ans=1,a[MN+5],head[MN*10+5],s[MN*10+5],size[MN*10+5],cnt=0;
    struct edge{int x,next;}e[MN*35+5];
    inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;}
    
    inline void Merge(int x,int y)
    {
        x=s[x];y=s[y];size[y]+=size[x];
        for(rint i=head[x];i;i=e[i].next)    
            ans-=(e[i].x!=1&&a[e[i].x-1]==y)+(e[i].x!=n&&a[e[i].x+1]==y);
        for(rint i=head[x];i;i=e[i].next)
            ins(y,e[i].x),a[e[i].x]=y;
        head[x]=size[x]=0;
    }
    
    int main()
    {
        n=read();m=read();
        for(rint i=1;i<=n;++i) a[i]=read(),s[a[i]]=a[i];
        for(rint i=1;i<=n;++i) ++size[a[i]],ins(a[i],i),ans+=(i!=1&&a[i]!=a[i-1]);
        for(rint i=1;i<=m;++i)
        {
            int op=read();
            if(op==1) 
            {
                int x=read(),y=read();if(x==y) continue;
                if(size[s[x]]>size[s[y]]) swap(s[x],s[y]);
                Merge(x,y);s[x]=0;
            }
            else printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    1167E (尺取法)
    Report CodeForces
    Maximum Xor Secondary CodeForces
    Sliding Window POJ
    单调队列 Sliding Window POJ
    尺取法
    目标
    NOIP系列(续)
    NOIP系列
    近期目标
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1483.html
Copyright © 2020-2023  润新知