bzoj 4610 Ceiling Functi

本文解决bzoj4610 CeilingFunction问题,通过暴力构造二叉搜索树并利用并查集统计不同树形态数量的方法,给出了完整的C++代码实现。

bzoj 4610 Ceiling Functi

Description

bzoj上的描述有问题
给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树。

Input

第一行包含两个数\(n(1 \lt n \le 50)\)代表数列的数量,\(k(1 \le k \le 20)\)代表每个堆的插入序列长度。
接下来\(n\)行每行包含\(k\)个数代表每个数列。

Output

输出不同树的形态数。

Sample Input

12 7
291388 78619 945367 867244 966006 445425 648278
593908 292543 111985 66151 846350 93727 765366
790325 950781 514834 937591 3749 922704 723259
788203 256144 944013 558440 591881 795482 173898
324286 386153 624883 475996 120001 18438 300906
819238 889730 825701 320745 611539 492070 410382
528593 425310 458894 528505 488435 192846 682984
564357 635943 41024 396434 286305 274829 196124
851238 206925 126110 537002 246374 859835 936366
729469 815045 965455 104000 364877 151376 759750
670021 748323 53559 609778 106547 151277 766524
561059 895615 951857 781815 378082 703670 620446

Sample Output

12

题解

首先吐槽bzoj翻译
其实此题就是一个大水题。因为数据很小,我们直接暴力建树和判断,用并查集统计。

#include <cstdio>
#include <cstring>
#define MS 1010
#define N 52
int root[N], ch[2][MS], v[MS], totNode;
int fa[N];
int find(int a) { return (fa[a]^a)?fa[a]=find(fa[a]):a; }
void Insert(int &u, const int &val) {
    if (!u) {
        v[u = ++totNode] = val; ch[0][u] = ch[1][u] = 0;
    } else {
        if (val < v[u]) Insert(ch[0][u], val);
        else Insert(ch[1][u], val);
    }
}
bool diff(int u, int v) {
    if (!u && !v) return false;
    if (!u || !v) return true;
    return diff(ch[0][u], ch[0][v]) || diff(ch[1][u], ch[1][v]);
}

int main() {
    int n, k, i, j, a, x, y;
    scanf("%d%d", &n, &k);
    for (i = 1; i <= n; ++i) {
        fa[i] = i;
        for (j = 1; j <= k; ++j) {
            scanf("%d", &a);
            Insert(root[i], a);
        }
    }
    a = 0;
    for (i = 1; i <= n; ++i)
      for (j = 1; j < i; ++j)
        if (!diff(root[i], root[j])) {
            x = find(i), y = find(j);
            if (x ^ y) fa[x] = y;
        }
    for (i = 1; i <= n; ++i) a += fa[i] == i;
    printf("%d\n", a);
    return 0;
}

转载于:https://www.cnblogs.com/cycleke/p/5927314.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值