BZOJ1098:[POI2007]办公楼biu 补图+链表+BFS
BZOJ2084:[Poi2010]Antisymmetry hash+二分

BZOJ1483:[HNOI2009]梦幻布丁 链表启发式合并

shinbokuow posted @ Dec 26, 2014 05:38:10 PM in BZOJ with tags 链表 启发式合并 , 2820 阅读

 

思路:

保存所有颜色组成的链表,改颜色时就把两个链表合并,合并方式利用归并排序即可.

易知链表的数目只会越来越少,因此我们进行启发式合并,每一次将小的链表合并到大的链表里面.

这样最坏情况下只需合并\(O(logn)\)次,每一次合并复杂度为\(O(n)\),因此总的时间复杂度为\(O(nlogn)\).

#include<cstdio>
#include<cstring>
#include<cctype>
#include<climits>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
 
#define INF 0x3f3f3f3f
 
#define N 100010
struct Node{
    Node*nxt;
    int ins;
    Node(){}
    Node(int _ins):ins(_ins){}
}*null;
Node*begin[N],*end[N];int c[N],siz[N];
 
map<int,int>M;int id;
 
int Ask(int x){return M[x];}
 
int res;
inline void Merge(int x,int y,int to){//Merge color y to color x
    static Node*stk1[N],*stk2[N];
    int id1=0,id2=0;
    int labx=M[x],laby=M[y],lastans=0,nowans=0;
    for(Node*p=begin[labx];p!=null;p=p->nxt)stk1[++id1]=p,lastans+=p->nxt->ins-p->ins>1;
    for(Node*p=begin[laby];p!=null;p=p->nxt)stk2[++id2]=p,lastans+=p->nxt->ins-p->ins>1;
    int i=1,j=1;
    Node*last=new Node(0),*S=last;
    for(;i<=id1&&j<=id2;last=last->nxt)
        if(stk1[i]->ins<stk2[j]->ins)last->nxt=stk1[i++];else last->nxt=stk2[j++];
    while(i<=id1)last->nxt=stk1[i++],last=last->nxt;
    while(j<=id2)last->nxt=stk2[j++],last=last->nxt;
    last->nxt=null;
    for(Node*p=S->nxt;p!=null;p=p->nxt)nowans+=p->nxt->ins-p->ins>1;
    begin[labx]=S->nxt;
    siz[labx]+=siz[laby];
    int t=M[x];M[x]=M[y]=0,M[to]=t;
    res=res-lastans+nowans;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("tt.in","r",stdin);
    #endif
 
    int n,m;scanf("%d%d",&n,&m);
    register int i,j;int x;
 
    null=new Node(INF);
 
    int now;
    for(i=1;i<=n;++i){
        scanf("%d",&x);
        if(!M[x])M[x]=++id;++siz[now=M[x]];
        Node*p=new Node(i);
        if(end[now])end[now]->nxt=p,end[now]=p;
        else begin[now]=end[now]=p;
    }
    for(i=1;i<=id;++i)end[i]->nxt=null;
 
    for(i=1;i<=id;++i)
        for(Node*p=begin[i];p!=null;p=p->nxt)res+=p->nxt->ins-p->ins>1;
 
    int qte,a,b;
    while(m--){
        scanf("%d",&qte);
        if(qte==1){
            scanf("%d%d",&a,&b);
            if(a==b)continue;
            if(M[a]==0)continue;
            if(!M[b]){M[b]=M[a],M[a]=0;continue;}
            if(siz[M[a]]>siz[M[b]])Merge(a,b,b);else Merge(b,a,b);
        }
        else printf("%d\n",res);
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter