zoukankan      html  css  js  c++  java
  • BZOJ 4569: [Scoi2016]萌萌哒 [并查集 倍增]

    传送门

    题意:长为$n le 10^5$的数字,给出$m le 10^5$个限制$[l1,r1] [l2,r2]$两个子串完全相等,求方案数


    把所有要求相等的位置连起来,不就是$9*10^{连通块个数}$嘛

    但是最坏情况要连$nm$次啊

    有很多都是重复的太浪费了

    于是各种乱搞,甚至想了一下分块,即使能减少边的条数也不能减少计算时会走的边的次数

    然后看题解,竟然是用倍增来优化

    有道理啊,分块太死板了,倍增的话就可以灵活的得到每个区间

    $fa[i][j]$表示从i开始$2^j$个数的区间的父亲(也就是和$fa[i][j]$开始$2^j$个数完全相等)

    合并的时候从高层往低层合并(j大到小),遇到fa相同就停下

    貌似一次合并最坏也是$O(n)$啊

    这里卡了我好久. 每层最多合并$n$次,一共$logn$层,没问题啊

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=1e5+5, P=1e9+7;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n, m, l1, r1, l2, r2;
    int fa[N][18], Log[N];
    int find(int i, int j) {return i==fa[i][j] ? i : fa[i][j]=find(fa[i][j], j);}
    void Union(int x, int y, int j) {
        int f1=find(x, j), f2=find(y, j);
        if(f1==f2) return;
        fa[f1][j]=f2;
        if(j) Union(x, y, j-1), Union(x + (1<<(j-1)), y+ (1<<(j-1)), j-1);
    }
    ll Pow(ll a, int b) {
        ll ans=1;
        for(; b; b>>=1, a=a*a%P)
            if(b&1) ans=ans*a%P;
        return ans;
    }
    
    int main() {
        freopen("in","r",stdin);
        n=read(); m=read();
        if(n==1) {puts("10"); return 0;}
        Log[1]=0; 
        for(int i=2; i<=n; i++) Log[i]=Log[i>>1]+1;
        for(int i=1; i<=n; i++)
            for(int j=0; j<=17; j++) fa[i][j]=i;
        for(int i=1; i<=m; i++) {
            l1=read(), r1=read(), l2=read(), r2=read();
            int t=Log[r1-l1+1];
            Union(l1, l2, t); Union(r1-(1<<t)+1, r2-(1<<t)+1, t);
        }
        int ans=0;
        for(int i=1; i<=n; i++) ans += find(i, 0)==i;
        printf("%lld
    ", 9*Pow(10, ans-1)%P);
    }
  • 相关阅读:
    使用postMan调用web services wsdl接口
    Python的入门基础(Linux、python、git)
    CrossoverQA文档
    Linux_磁盘分区、挂载、查看
    Linux为什么要挂载
    图解Windows10+优麒麟双系统安装
    Linux 软件安装与卸载
    ventroy 制作多系统启动盘
    字节跳动面试官:请你实现一个大文件上传和断点续传
    关于本博客和博主
  • 原文地址:https://www.cnblogs.com/candy99/p/6596589.html
Copyright © 2011-2022 走看看