zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    深入理解JavaScript的闭包特性 如何给循环中的对象添加事件
    兼容低版本浏览器的getElementByClassName方法
    印象深刻的bug
    pyinstaller将python编写的打卡程序打包成exe
    自动化环境搭建遇到问题
    VS2010带不出System.Data.OracleClient这个引用的解决方案
    迭代与列表生成式、生成器
    Python函数
    Python基础
    python+Selenium 环境搭建
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1483.html
Copyright © 2011-2022 走看看