zoukankan      html  css  js  c++  java
  • luogu P3201 [HNOI2009]梦幻布丁

    传送门

    先考虑暴力,显然每次是把一个位置集合和另一个集合合并,同时维护答案,合并的过程中如果两个集合每有一对元素相邻,答案就减1

    优化暴力的话,说到合并,怎么能不想起启发式合并呢?每次把一个大小小的集合并到大的上面,如果一个元素合并一次是(O(1)),总复杂度就是(O(nlogn)).实现的化可以使用平衡树/set,也可以大力链表

    注意可能本来是(x)变成(y)颜色的,但是因为启发式合并,交换(x,y)以后变成(y)(x),这样会出问题,这个时候要用(f_x)表示(x)指代的颜色,然后交换只要交换(f)救星了

    更多细节详见代码

    #include<bits/stdc++.h>
    #define LL long long
    #define db double
    #define il inline
    #define re register
    
    using namespace std;
    const int N=1e6+10;
    il int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int n,m,c[N],ans,f[N],sz[N],nt[N],hd[N],tl[N];
    
    int main()
    {
        n=rd(),m=rd();
        for(int i=1;i<=n;++i)
        {
            c[i]=rd(),ans+=c[i]!=c[i-1];
            f[c[i]]=c[i];
            if(!tl[c[i]]) hd[c[i]]=i;
            else nt[tl[c[i]]]=i;
            ++sz[c[i]],tl[c[i]]=i;
        }
        while(m--)
        {
            int op=rd();
            if(op==1)
            {
                int &x=f[rd()],&y=f[rd()];
                if(x==y) continue;
                if(sz[x]>sz[y]) swap(x,y);
                if(!sz[x]) continue;
                for(int i=hd[x];i;i=nt[i]) ans-=(c[i-1]==y)+(c[i+1]==y);
                for(int i=hd[x];i;i=nt[i]) c[i]=y;
                nt[tl[x]]=hd[y],hd[y]=hd[x],sz[y]+=sz[x],x=sz[x]=hd[x]=tl[x]=0;
            }
            else printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    RDD, DataFrame or Dataset
    RDD的基础知识
    RDD的源码
    窄依赖与宽依赖&stage的划分依据
    HDFS中的读写数据流
    HDFS的Java API
    使用distcp并行拷贝大数据文件
    Flume+Morphlines实现数据的实时ETL
    磕碰,擦伤了,紧急处理方法
    redis linux 基本命令
  • 原文地址:https://www.cnblogs.com/smyjr/p/10410349.html
Copyright © 2011-2022 走看看