zoukankan      html  css  js  c++  java
  • bzoj1483

    启发式合并,在合并时将siz较小的合并到siz较大的后面

    题意: 
    有两个操作 
    1、将所有的x改成y 
    2、求序列的颜色段 如1 2 2 1 ans=2(m<=1000000) 
    首先,可以求出初始序列的ans,然后每次修改颜色相当于合并两个颜色,启发式合并。 
    启发式合并就是将sz小(s1)的暴力加入sz大的(s2),因为sz[s1]至少翻倍,至多翻倍至totsz,所以复杂度是O(logn)

    附上并不知道正确性的代码

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define maxn 1000010
    using namespace std;
    int n,m,ans,a[maxn],head[maxn],nex[maxn],f[maxn],sz[maxn];
    
    void insert(int col,int wher){
        int tmp=head[col];head[col]=wher;nex[wher]=tmp;
    }
    
    void merge(int &x,int &y){
        x=f[x];y=f[y];
        if(x==y)return;
        if(sz[x]>sz[y])swap(x,y);
        if(head[x]==0)return;
        for(int i=head[x];i;i=nex[i]){
            if(a[i+1]==y)ans--;
            if(a[i-1]==y)ans--;
        }
        for(int i=head[x];i;i=nex[i])a[i]=y;
        int k;
        for(k=head[y];k;k=nex[k]);
        nex[k]=head[x];sz[y]+=sz[x];sz[x]=head[x]=0;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(a[i]!=a[i-1])ans++;
            f[a[i]]=a[i];sz[a[i]]++;
            insert(a[i],i);
        }
        while(m--){
            int typ;
            scanf("%d",&typ);
            if(typ==1){int x,y;merge(x,y);}else printf("%d\n",ans);
        }
    }
  • 相关阅读:
    bzoj1589[Usaco2008 Dec]Trick or Treat on the Farm 采集糖果*
    bzoj1672[Usaco2005 Dec]Cleaning Shifts 清理牛棚*
    bzoj1691[Usaco2007 Dec]挑剔的美食家*
    bzoj1637[Usaco2007 Mar]Balanced Lineup*
    LinkedList源码
    链表
    反向打印链表
    空格替换
    二维数组查找
    待编辑
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/8987641.html
Copyright © 2011-2022 走看看