zoukankan      html  css  js  c++  java
  • SCOI2016萌萌哒题解

    SCOI2016萌萌哒题解

    题目链接


     

    思路

    这个题目大概就是给你一些限制,使区间相等,那么一个很巧妙的思路就是将区间限制转化为两个店在一个并查集里

    我们要求的是只有一位的并查集的个数,答案为 
    ( t我们要求的是只有一位的并查集的个数)

    但直接操作复杂度过大

    于是有人想到了倍增

    f[i][j]表示区间[ , ]所在的并查集

    最开始时记录每个大区间的左右儿子

    输入 l1 l2 r1 r2时像ST表一样合并

    再分别处理每个大区间,如果f[i][j]f[a][b]在一个并查集里,那么他们的左右儿子也在一个并查集里,我们就能将大区间合并信息下传为左右儿子的合并(左儿子与左儿子合并,右儿子与右儿子合并)

    最后统计f[i][0]的并查集个数即可

     

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define re register int
    #define ll long long
    #define MN 1000050
    #define mod 1000000007
    using namespace std;
    int bcj[MN*22],f[MN][22],lc[MN*22],rc[MN*22],lg[MN];
    int n,m,k,ltk,cnt;
    int find(int x){
        if(x==bcj[x])return x;
        bcj[x]=find(bcj[x]);
        return bcj[x];
    }
    void merge(int x,int y){
        int t1=find(x),t2=find(y);
        if(t1!=t2)bcj[t2]=t1;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(re i=2;i<=n;i++)
            lg[i]=lg[i/2]+1;    
        for(re j=lg[n];j>=0;j--)
            for(re i=1;i+(1<<j)-1<=n;i++){
                    f[i][j]=++cnt;
                    bcj[cnt]=cnt;
            }//给大区间编号
        for(re j=1;j<=lg[n];j++)
            for(re i=1;i+(1<<j)-1<=n;i++){
                lc[f[i][j]]=f[i][j-1];
                rc[f[i][j]]=f[i+(1<<(j-1))][j-1];
            }//统计左右儿子
        for(re i=1;i<=m;i++){
            int a1,a2,a3,a4;
            scanf("%d%d%d%d",&a1,&a2,&a3,&a4);
            int l=lg[a2-a1+1];
            merge(f[a1][l],f[a3][l]);
            merge(f[a2-(1<<l)+1][l],f[a4-(1<<l)+1][l]);
        }//像st表一样合并
        for(re i=1;i<=cnt;i++){
            if(!lc[i]||!rc[i])continue;
            int t1=find(i);
            if(t1!=i){
                merge(lc[t1],lc[i]);
                merge(rc[t1],rc[i]);
                //如果f[i][j]与f[a][b]同属一个联通块,那么他们左右儿子也同属一个联通块
            }
        }
        ltk=n;
        //先假设每个位置都是独立的联通块,如果联通再减
        for(re i=1;i<=n;i++){
            if(find(f[i][0])!=f[i][0])
                ltk--;
        }
        ll ans=9;
        for(re i=1;i<ltk;i++)
            ans=(ans%mod*10)%mod;
            printf("%lld",ans%mod);
        return 0;
    }
    缘分让我们相遇乱世以外, 命运却要我们危难中相爱。 也许未来遥远在光年之外, 我愿守候未知里为你等待。
  • 相关阅读:
    Python疑难杂症:SyntaxError: NonASCII character Python中文处理问题
    程序员健康大全透视身体24小时工作时间表
    ConnectionTimeout,CommandTimeout和executionTimeout的理解
    google map api 与jquery结合使用(3) 图标样式,使用xml和异步请求【转帖】
    新手8周跑步训练计划
    57商城温州地区最大本土网上超市
    7 款仿照 Sinatra 思路的 .NET 框架
    线程池的原理和连接池的原理
    免费网站模版:一个黑色系的公司网站模版(flash幻灯)
    深入浅出REST
  • 原文地址:https://www.cnblogs.com/zw130-lzr-blogs/p/11274501.html
Copyright © 2011-2022 走看看