码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ1483】【HNOI2009】梦幻布丁

时间:2017-05-09 11:27:15      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:lan   启发式   http   想法   利用   复杂   getchar   颜色   printf   

题意:n个连续的点,有若干种颜色,每个颜色会因为某些操作变为另一种颜色,动态查询颜色段数。

解题思路:对每个颜色开一棵平衡树启发式合并应该是最裸的想法,但是我们有更优的!

考虑对每个颜色利用链表储存它的集合,在合并两种颜色时可以很简单通过对比原节点位置的前后颜色来进行答案的更新,然后利用启发式合并进行保证合并效率即可。

总复杂度: \( O( q \log c ) \) / \( O (c) \) C表示颜色数。(目前是BZOJ Rank2 200ms)

#include <stdio.h>
#define MN 100005
#define MC 1000005
#define r register
#define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++)
char BB[1<<15],*S=BB,*TT=BB;
inline int read(){
    r int x=0;r char c;
    for (;(c=getchar())<0||c>9;);
    for (x=c-0;(c=getchar())>=0&&c<=9;x=(x<<3)+(x<<1)+c-0);
    return x;
}
inline void swap(int &a,int &b){a^=b^=a^=b;}
int rt[MC],nxt[MN],s[MC],col[MN],n,q,ans;
inline void merge(int x,int y){
    if (s[x]>s[y]){swap(x,y);}
    for (r int i=rt[x]; i; i=nxt[i]){
        ans-=(col[i-1]==y)+(col[i+1]==y);
        if (!nxt[i]){nxt[i]=rt[y];break;}
    }for (r int i=rt[x]; i!=rt[y]; i=nxt[i]) col[i]=y;
    rt[y]=rt[x];s[y]+=s[x];s[x]=rt[x]=0; 
}
void init(){
    n=read(),q=read();ans=1;
    for (int i=1; i<=n; ++i) col[i]=read(),nxt[i]=rt[col[i]],rt[col[i]]=i;
    for (r int i=2; i<=n; ++i) if (col[i]!=col[i-1]) ++ans;
}
void solve(){
    while(q--){
        r int op=read();
        if (op==1){r int x=read(),y=read();if (x!=y) merge(x,y);}
        else printf("%d\n",ans);
    }
}
int main(){init();solve();return 0;}

 

【BZOJ1483】【HNOI2009】梦幻布丁

标签:lan   启发式   http   想法   利用   复杂   getchar   颜色   printf   

原文地址:http://www.cnblogs.com/Melacau/p/BZOJ1483.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!