zoukankan      html  css  js  c++  java
  • 【ST表】SCOI2016 萌萌哒

    题目内容

    洛谷链接
    一个长度为(n)的大数,用(S_1S_2S_3...S_n)表示,其中(S_i)表示数的第(i)位,(S_1)是数的最高位,告诉你一些限制条件,每个条件表示为四个数,(l_1,r_1,l_2,r_2,)即两个长度相同的区间,表示子串(S_{l1}S_{l1+1}S_{l1+2}...S_{r1})(S_{l2}S_{l2+1}S_{l2+2}...S_{r2})完全相同。比如(n=6)时,某限制条件(l_1=1,r_1=3,l_2=4,r_2=6,)那么(123123)(351351)均满足条件,但是(12012)(131141)不满足条件,前者数的长度不为6,后者第二位与第五位不同。问满足以上所有条件的数有多少个。

    输入格式

    第一行两个数(n)(m),分别表示大数的长度,以及限制条件的个数。接下来(m)行,对于第(i)行,有4个数(l_{i1},r_{i1},l_{i2},r_{i2}),分别表示该限制条件对应的两个区间。
    (1≤n≤10^5,1≤m≤10^5,1≤l_{i1},r_{i1},l_{i2},r_{i2}≤n)
    并且保证(r_{i1}-l_{i1}=r_{i2}-l_{i2})

    输出格式

    一个数,表示满足所有条件且长度为(n)的大数的个数,答案可能很大,因此输出答案模(10^9+7)的结果即可。

    样例输入

    4 2
    1 2 3 4
    3 3 3 3

    样例输出

    90

    思路

    并查集+ST表,利用倍增合并集合。

    代码

    #include <cmath>
    #include <cstdio>
    using namespace std;
    const int maxn=1e5+10;
    const int Mod=1e9+7;
    int n,m;
    int fa[maxn][20];//表示[i,i+2^j-1]
    long long ans;
    
    void init(int k){
        for (int i=1;i<=n;++i)
            for (int j=0; j<=k;++j)
                fa[i][j] = i;
    }
    
    int find(int x, int y){ 
        return x==fa[x][y] ? x : (fa[x][y]=find(fa[x][y],y));
    }
    
    void merge(int x, int y, int j){ 
        int fx=find(x,j),fy=find(y,j);
        if((fx!=fy))fa[x][j]=y;
    }
    
    int main() {
        scanf("%d %d", &n, &m);
        int maxj = floor(log2(n));//求一下最大倍增次数,也可以直接用20
    
        init(maxj);
    
        for (int i=1;i<=m;++i){
            int l1,r1,l2,r2;
            scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
            for (int j=maxj;j!=-1;--j)
                if (l1+(1<<j)-1<=r1){
                    merge(l1,l2,j);
                    l1+=1<<j;
                    l2+=1<<j;
                }
        }
    
        for (int j=maxj;j;--j)
            for (int i=1;i+(1<<j)-1<=n;++i) {
                int fath=find(i,j);
                merge(i,fath,j-1);
                merge(i+(1<<j-1),fath+(1<<j-1),j-1);
            }
    
        for(int i=1;i<=n;++i)
            if (fa[i][0]==i)ans=!ans ? 9 : ans*10%Mod;
    
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    vim for python配置
    Python学习的一些好资料
    【Python开发实战】Python环境的配置
    【Python开发实战】Windows7+VirtualBox+Ubuntu环境配置
    linux下shapely的安装
    【python常用模块】os.path
    linux下gdal的python包的安装
    由二叉树的前序遍历和中序遍历,求其后序遍历
    ASCII码表
    C++标准库函数之排列函数
  • 原文地址:https://www.cnblogs.com/Midoria7/p/12827481.html
Copyright © 2011-2022 走看看