• BZOJ 4569 萌萌哒


    题目传送门

    4569: [Scoi2016]萌萌哒

    Time Limit: 10 Sec Memory Limit: 256 MB

    Submit: 483 Solved: 221

    [Submit][Status][Discuss]

    ## **Description** 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条 件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1+1Sl1+2...Sr1与Sl2Sl2+1Sl2+2...S r2完全相同。比如n=6时,某限制条件l1=1,r1=3,l2=4,r2=6,那么123123,351351均满足条件,但是12012,13 1141不满足条件,前者数的长度不为6,后者第二位与第五位不同。问满足以上所有条件的数有多少个。 ## **Input** 第一行两个数n和m,分别表示大数的长度,以及限制条件的个数。接下来m行,对于第i行,有4个数li1,ri1,li2 ,ri2,分别表示该限制条件对应的两个区间。 1≤n≤10^5,1≤m≤10^5,1≤li1,ri1,li2,ri2≤n;并且保证ri1-li1=ri2-li2。 ## **Output** 一个数,表示满足所有条件且长度为n的大数的个数,答案可能很大,因此输出答案模10^9+7的结果即可。 ## **Sample Input** 4 2 1 2 3 4 3 3 3 3 ## **Sample Output** 90 ## **题解** 这道题显然要用并查集,不过需要进行区间合并。所以我最开始选择了线段树···· 在经历千辛万苦之后,我确定了线段树并不能搞定此题。 看此题数据,我们就蒙一个$O(nlog (n))$级的算法。这样我们可以用f[i][j]来表示一段区间的父亲。 最暴力的方法就是表示i..j区间的父亲,但显然会炸。我们就联想到倍增,用f[i][j]表示i..i+(2^j)-1的区间父亲。 这样我们对于每一个区间的合并,我们最多进行$log n$次合并,在算上并查集的$O(alpha (a))$ ,总的复杂度为$O(nlog n alpha (a))$ 。 ``` c++ #include //Input char Inc; int Ina; inline int geti() { while ((Inc = getchar()) < '0' || Inc > '9'); Ina = Inc - '0'; while ((Inc = getchar()) >= '0' && Inc <= '9') Ina = (Ina << 3) + (Ina << 1) + Inc - '0'; return Ina; } // const int Mod = 1e9 + 7, N = 100005; int f[N][17]; bool vis[N]; int find(int i, int j) { return (f[i][j] ^ i) ? f[i][j] = find(f[i][j], j) : i; }

    void Union(int k, int i, int j) {
    if (find(i, k) ^ find(j, k)) {
    f[f[i][k]][k] = f[j][k];
    if (!k--) return;
    Union(k, i, j); Union(k, i + (1 << k), j + (1 << k));
    }
    }

    int main() {
    int n, m, i, j, a, b, c, d, ans;
    n = geti(), m = geti();
    if (n < 2) return puts("9"), 0;
    for (j = 0; (1 << j) <= n; ++j)
    for (i = 1; i + (1 << j) - 1 <= n; ++i)
    f[i][j] = i;
    while (m--) {
    a = geti(), b = geti(), c = geti(), d = geti();
    j = b - a + 1, i = 0;
    while ((1 << i + 1) <= j) ++i;
    Union(i, a, c); Union(i, b - (1 << i) + 1, d - (1 << i) + 1);
    }
    ans = 9; vis[find(1, 0)] = true;
    for (i = 2; i <= n; ++i) if (!vis[find(i, 0)]) vis[find(i, 0)] = true, ans = 10LL * ans % Mod;
    printf("%d ", ans);
    return 0;
    }

  • 相关阅读:
    net core 使用 rabbitmq
    asp.net core WebApi 返回 HttpResponseMessage
    asp.net core 2.1 WebApi 快速入门
    JQuery EasyUI combobox动态添加option
    php截取字符去掉最后一个字符
    JQuery EasyUI Combobox的onChange事件
    对于不返回任何键列信息的 selectcommand 不支持 updatecommand 的动态 sql 生成
    Access2007 操作或事件已被禁用模式阻止解决办法
    Easyui 中 Tabsr的常用方法
    Win 7 IE11不能下载文件,右键另存为也不行
  • 原文地址:https://www.cnblogs.com/cycleke/p/5838890.html
Copyright © 2020-2023  润新知