首页 > 其他分享 >ABC306F Merge Sets

ABC306F Merge Sets

时间:2024-01-31 22:11:27浏览次数:34  
标签:元素 ABC306F leq int sum cap Merge Sets 集合

原题链接

分析

观察要求的式子:\(\sum_{1 \leq i \lt j \leq N}f(S_i, S_j)\),发现可以拆成每一个集合 \(S_i\) 的贡献的和。那么我们考虑每一个集合 \(S_i\) 的贡献。

显然,对于每一个 \(S_i\) ,其贡献就是 \(\sum_{i \lt j \leq N}f(S_i, S_j)\),也就是它与其后每一个集合 \(S_j\) 的 \(f\) 函数值相加。那么现在我们来深入剖析一下 \(f(A, B)\) 到底是什么。

观察题目描述 \(f(A,B)\) 的例子:

For example, if A = {1, 3} and B = {2, 8}, then C = (1, 2, 3, 8), so A = {C1, C3}; Thus, f(A, B) = 1 + 3 = 4.

这个例子告诉我们 \(f\) 的函数值实际上可以看成集合 \(A\) 中每个元素对其造成的贡献的和。

上结论:\(f(A, B)\) 的函数值是 \(A\) 中所有元素 在两个集合并起来的所有数 中的排名 的和。这个看例子应该就能明白了。考虑排名的定义:数列中 比某个数小的数 的个数 加一。定义 \(R(S, x)\) 为集合 \(S\) 中比 \(x\) 小的数的个数。那么 \(f(A, B)\) 可以被表示为

\(\sum_{1 \leq i \leq |A|}(R(A \cap B, A_i)+1).\)

由于 \(A\) 和 \(B\) 的交集是空集,所以可以将上式拆开:

\(f(A, B) = \sum_{1 \leq i \leq |A|}(R(A, A_i) + R(B, A_i)+1).\)

看到第二项 \(R(B, A_i)\),立刻想到在值域上建立树状数组。于是前一项也就好搞了。做法:先把 \(B\) 里的每个元素扔到树状数组里,然后按顺序扫过 \(A\) 的每个元素,先查询比这个元素小的数 的个数 加到 \(ans\) 里,然后把这个元素也扔到树状数组里。扫完之后 \(ans\) 就是 \(f(A, B)\) 的值。

现在来发掘一下 \(f\) 函数的性质。

注:以下所指的任意两个集合 互相的交集 都是空集

$f(A, B) + f(A, C) = $

\(\sum_{1 \leq i \leq |A|}(R(A, A_i) + R(B, A_i)+1) + \sum_{1 \leq i \leq |A|}(R(A, A_i) + R(C, A_i)+1)\)

\(=\sum_{1 \leq i \leq |A|}(2R(A, A_i) + R(B, A_i) + R(C, A_i) + 2)\)

\(=\sum_{1 \leq i \leq |A|}(2R(A, A_i)+R(B \cap C, A_i)+2)\)

\(=2|A| + \sum_{1 \leq i \leq |A|}(2R(A, A_i) + R(B \cap C, A_i)).\)

同样的,这种性质也可以扩展到多个加数的情况,只要所有加数的第一个参数都是同一个集合:

\(f(A, S_1) + f(A, S_2) + f(A, S_3) + ... + f(A, S_n)\)

\(= n|A| + \sum_{1 \leq i \leq |A|}(nR(A, A_i) + R(S_1 \cap S_2 \cap S_3 ... \cap S_n, A_i)).\)

那么现在来考虑单个集合 \(S_i\) 的贡献 \(\sum_{i \lt j \leq N}f(S_i, S_j)\)。

\(\sum_{i \lt j \leq N}f(S_i, S_j)\)

\(=f(S_i, S_{i + 1})+f(S_i, S_{i+2})+...+f(S_i, S_N)\)

\(=(N-i)|S_i|+\sum_{1\leq j \leq m}((N-i)R(S_i, S_{i_j})+R(S_{i+1} \cap S_{i+2} \cap ... S_N, S_{i_j})).\)

如果将 \(S_i\) 排序后从前往后扫,那么 \(R(S_i, S_{i_j})\) 其实就等于 \(j - 1\)。所以上式

\(=(N-i)|S_i|+\sum_{1\leq j \leq m}((N-i)(j-1)+R(S_{i+1} \cap S_{i+2} \cap ... S_N, S_{i_j})).\)

求和号中的第一项好算。而第二项其实是每一个 \(S_{i_j}\) 在 其后所有集合 的并 中的排名。我们倒序扫每个集合,从小到大扫集合里的每个数,和之前一样树状数组即可。

这里有一点需要注意的是由于我们每次处理完一个元素之后就会将其扔进树状数组里,故该集合的后续元素 会将这个元素考虑进其贡献。但是这种集合内部的贡献是不在刚才那个和式的第二项中的。我们考虑其大小,发现第 \(j\) 个元素收到的这种贡献实际上就是 \(j - 1\)。于是可以直接把它跟第一项合并。

代码

#include <iostream>
#include <algorithm>
#include <map>
#define int long long
#define lowbit(x) ((x) & -(x))
using namespace std;
int a[10005][105];
int d[1000005];
int bit[1000005];
void add(int x) { for (; x <= 1000000; x += lowbit(x)) bit[x]++; }
int query(int x) {
    int ret = 0;
    for (; x; x -= lowbit(x)) ret += bit[x];
    return ret;
}
map<int, int> mp;
signed main() {
    int n, m, cnt = 0;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> a[i][j];
            d[++cnt] = a[i][j];
        }
        sort(a[i] + 1, a[i] + m + 1);
    }
    int ans = 0;
    sort(d + 1, d + cnt + 1);
    for (int i = 1; i <= cnt; i++) mp[d[i]] = i; // 只会用 map 离散化的屑(指我
    for (int i = n; i >= 1; i--) {
        for (int j = 1; j <= m; j++) {
            a[i][j] = mp[a[i][j]];
            ans += query(a[i][j]) + (j - 1) * (n - i - 1); // n - i 减去 1 就是为了应对集合内贡献
                                             // query(a[i][j]) 就是和式里的第二项
            add(a[i][j]);
        }
    }
    for (int i = 1; i <= n; i++) {
        ans += m * (n - i); // 和式前面的项
    }
    cout << ans;
    return 0;
}

完结撒花~~

标签:元素,ABC306F,leq,int,sum,cap,Merge,Sets,集合
From: https://www.cnblogs.com/forgotmyhandle/p/18000237

相关文章

  • SQL Server MERGE(合并)语句
    来源 https://www.cnblogs.com/yigegaozhongsheng/p/11941734.html如何使用SQLServerMERGE语句基于与另一个表匹配的值来更新表中的数据。  SQLServer MERGE语句 假设有两个表,分别称为源表和目标表,并且需要根据与源表匹配的值来更新目标表。有以下三种情况: 源表......
  • QSplitter 分割 组件之setStretchFactor方法
    原型:voidQSplitter::setStretchFactor(intindex,intstretch)翻译:将索引位置的部件的大小策略更新为具有拉伸因子stretch。stretch不是实际的拉伸因子;实际的拉伸因子是通过将部件的初始大小乘以stretch来计算的。根据实际情况可知,如果俩个控件默认大小一样,若下标0的拉伸因......
  • 无涯教程-Swift - 集合(Sets)
    Swift4Sets用于存储相同类型的不同值,但它们没有数组的确定顺序,如果要确保没有重复的值,则可以使用Set集合而不是数组。创建Set集您可以使用以下初始化语法创建一个特定类型的空集-varsomeSet=Set<Character>()//字符可以替换为set的数据类型。访问和修改您可以使用......
  • Git必知必会基础(12):远程冲突(conflicts)解决--merge
     演示场景虽然每次合并代码前会先把分支更新到最新,但是在你pull后到push前这段时间,可能其它小伙伴又push了,那么你的分支就不是最新的了在push的时候就会失败,比如遇到这种提示信息:Togitee.com:qzcsbj/pytest_apiautotest.git![rejected]master->master(fetchfirst)error:......
  • 无涯教程-Scala Sets函数
    ScalaSets是同一类型的不同元素的集合,换句话说,集合是不包含重复元素的集合。默认情况下,Scala使用不可变的Set。如果要使用可变Set,则必须显式导入scala.collection.mutable.Set类,如果要在同一集合中同时使用可变集和不可变集,则可以继续将不可变集称为Set,但可以将可变集称为......
  • 使用mergekit 合并大型语言模型
    模型合并是近年来兴起的一种新技术。它允许将多个模型合并成一个模型。这样做不仅可以保持质量,还可以获得额外的好处。假设我们有几个模型:一个擅长解决数学问题,另一个擅长编写代码。在两种模型之间切换是一个很麻烦的问题,但是我们可以将它们组合起来,利用两者的优点。而且这种组......
  • scikit-learn.datasets 机器学习库
    scikit-learn是一个用于Python的机器学习库,提供了大量用于数据挖掘和数据分析的工具。以下是对这些函数和方法的简要描述:clear_data_home:清除数据集目录的内容。dump_svmlight_file:将数据集保存为SVMLight格式的文件。fetch_20newsgroups:下载20个新闻组的文本数据集。f......
  • Unity的StreamAssets文件夹
    StreamAssets是一个特殊的文件夹,其中的内容在Unity打包的时候并不会被压缩,完整的带入包体介绍在做一个根据可变配置进行操作的功能时,突然发现在windows中正常的功能在mac上失效了,而且还是部分mac失效。发现StreamAssets在mac某个版本以上就不支持写操作了,搜了一下网上的资料......
  • Git必知必会基础(11):merge和rebase的区别
     本系列汇总,请查看这里:https://www.cnblogs.com/uncleyong/p/10854115.htmlmerge和rebase使用回顾上两篇我们分别演示了merge和rebase的使用,分别详见:https://www.cnblogs.com/uncleyong/p/17967432https://www.cnblogs.com/uncleyong/p/17978213下面我们来总结下二者的差异......
  • vscode windows CMakePresets.json
    vscode在windows下使用Ninja编译配置,使用VisualStudio编译环境。来源:CMakePresets.json参考:在VisualStudio中使用CMake预设进行配置和生成--示例文件CMakePresets.json{"version":2,"configurePresets":[{"name":"base","......