zoukankan      html  css  js  c++  java
  • Solution -「SCOI 2016」萌萌哒

    Description

    Link.

    给定一个长度为 (n) 的数组让你填数,需要满足 (m) 个形如 (([l_{1},r_{1}],[l_{2},r_{2}])) 的要求,这两个区间填好后需要一样,问方案数。

    Solution

    Let us only consider one limit (([l_{1},r_{1}],[l_{2},r_{2}])), the number of ways is (10^{r-l+1}).
    Connecting every (iin[l_{1},r_{1}]) and (jin[l_{2},r_{2}]), we can construct a graph.
    Counting the number of connected subgraphs, denoted as (x), the answer is (9 imes10^{x-1}), and the complexity is (mathcal{O}(n^{2}alpha(n))).
    Each interval could be splited into (log_{2}r-l+1) subintervals, so that we can solve this in (mathcal{O}(nlog_{2}nalpha(n))).

    #include <bits/stdc++.h>
    typedef long long ll;
    #define sf(x) scanf("%d",&x)
    #define ssf(x) scanf("%lld",&x)
    struct DSU {
        int fa[100010];
        void init(int l) {
            std::iota(fa + 1, fa + l + 1, 1);
        }
        int find(int x) {
            return (x ^ fa[x]) ? fa[x] = find(fa[x]) : x;
        }
        void ins(int x, int y) {
            if (x ^ y)
                fa[x] = y;
        }
    } dsu[20];
    int n, m, opl0, opr0, opl1, opr1;
    ll ans = 1;
    int main() {
        sf(n), sf(m);
    
        for (int i = 0; i ^ 20; ++i)
            dsu[i].init(n);
    
        while (m-- > 0) {
            sf(opl0), sf(opr0), sf(opl1), sf(opr1);
            int cur0 = opl0, cur1 = opl1;
    
            for (int i = 19; ~i; --i) {
                if (cur0 + (1 << i) - 1 <= opr0) {
                    dsu[i].ins(dsu[i].find(cur0), dsu[i].find(cur1));
                    cur0 += (1 << i);
                    cur1 += (1 << i);
                }
            }
        }
    
        for (int j = 19; j; --j) {
            for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
                dsu[j - 1].ins(dsu[j - 1].find(i), dsu[j - 1].find(dsu[j].find(i)));
                dsu[j - 1].ins(dsu[j - 1].find(i + (1 << (j - 1))), dsu[j - 1].find(dsu[j].find(i) + (1 << (j - 1))));
            }
        }
    
        for (int i = 1; i <= n; ++i)
            if (dsu[0].fa[i] == i)
                ans = ans * (ans == 1 ? 9 : 10) % 1000000007;
    
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    leetcode53. Maximum Subarray(动态规划)
    MinGW中没有gdb.exe解决办法
    POJ
    POJ 3614 (贪心)
    bzoj 1057 (悬线法求最大子矩阵)
    bzoj1 218 激光炸弹(二位前缀和)
    POJ 2299(归并求逆序对)
    HDU 1394(归并求逆序对)
    POJ1523 Targin求关节点
    HDU6299 贪心
  • 原文地址:https://www.cnblogs.com/orchid-any/p/14755029.html
Copyright © 2011-2022 走看看