zoukankan      html  css  js  c++  java
  • bzoj 4569 [Scoi2016]萌萌哒 并查集 + ST表

    题目链接

    Description

    一个长度为(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})完全相同。

    问满足以上所有条件的数有多少个。

    思路

    参考

    https://www.cnblogs.com/owenyu/p/7146428.html

    暴力想法

    对于每一个条件,将([l_1,r_1])([l_2,r_2])范围内对应的数一一(union)起来,最后检查有多少个集合(cnt),答案即为(10^{cnt-1}*9).

    优化

    运用(ST)表的思路,但形式与之相反。

    一般的(ST)表是从小区间中衍伸得到大区间的性质,本题则是从大区间向小区间推。

    (logn)个并查集,对于每一个条件,拆成前后两部分分别进行(union)

    最后从上往下推,将每层的每个大区间拆成下一层的两个小区间。

    最后检查最底层。

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    #define maxn 100000
    #define maxk 17
    using namespace std;
    typedef long long LL;
    bool vis[maxn+10];
    int sz[maxk+1][maxn+10], fa[maxk+1][maxn+10], Log[maxn+10], bi[maxk+1], n, m;
    inline int find(int dep, int x) {
        return fa[dep][x]==x ? x : fa[dep][x]=find(dep, fa[dep][x]);
    }
    inline void unionn(int dep, int x, int y) {
        x = find(dep, x), y = find(dep, y);
        if (x==y) return;
        if (sz[dep][x]>sz[dep][y]) swap(x, y);
        fa[dep][x] = y;
    }
    void init() {
        Log[0] = -1; bi[0] = 1;
        F2(i, 1, maxn) Log[i] = Log[i>>1]+1;
        int k=Log[n];
        F2(i, 1, maxk) {
            bi[i] = bi[i-1]<<1;
        }
        F2(i, 0, maxk) F2(j, 1, n) fa[i][j]=j, sz[i][j]=1;
    }
    const LL mod=1e9+7;
    LL poww(LL a, LL b) {
        LL ret=1;
        while (b) {
            if (b&1) (ret*=a)%=mod;
            (a*=a)%=mod;
            b>>=1;
        }
        return ret;
    }
    int main() {
        scanf("%d%d", &n,&m);
        init();
        F(i, 0, m) {
            int l1, r1, l2, r2;
            scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
            int dep=Log[r1-l1+1];
            unionn(dep, l1, l2);
            unionn(dep, r1-bi[dep]+1, r2-bi[dep]+1);
        }
        dF(dep, maxk, 0) {
            F2(i, 1, n) {
                int x=find(dep, i);
                unionn(dep-1, i, x);
                unionn(dep-1, i+bi[dep-1], x+bi[dep-1]);
            }
        }
        int ans=0;
        F2(i, 1, n) ans += (find(0, i)==i);
        printf("%lld
    ", poww(10, ans-1)*9%mod);
        return 0;
    }
    
    
  • 相关阅读:
    Kafka之消费者与消费者组
    Kafka之生产者
    基于Redis+Lua的分布式限流
    限流方案常用算法讲解
    分布式服务限流
    微服务框架服务调用与容错
    ZooKeeper实现服务注册中心
    微服务注册中心
    让我自己来整理
    Netty框架
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/8516377.html
Copyright © 2011-2022 走看看