二分+前缀(预处理神力2)

1. 问题

我们要计算:

复制代码
S=i=1∑N​j=1∑M​∣Ai​−Bj​∣mod998244353

其中 N,M≤3×105,不能暴力 O(NM)。

2. 数学推导

对于每个固定的 Ai​:

复制代码
j=1∑M​∣Ai​−Bj​∣=Bj​≤Ai​∑​(Ai​−Bj​)+Bj​>Ai​∑​(Bj​−Ai​)

设 k= 小于等于 Ai​的 Bj​的数量,S≤​= 这些 Bj​的和,S>​= 大于 Ai​的 Bj​的和,且 S>​=sum(B)−S≤​。

则:

复制代码
贡献=(Ai​⋅k−S≤​)+((S>​)−Ai​⋅(M−k))

整理:

复制代码
=Ai​⋅k−S≤​+S>​−Ai​⋅M+Ai​⋅k
复制代码
=(2k−M)⋅Ai​+(S>​−S≤​)
复制代码
=(2k−M)⋅Ai​+(sum(B)−2S≤​)

3. 算法步骤

  1. 对 B排序

  2. 计算 B的前缀和数组

  3. 对每个 Ai​:

    • 在排序后的 B中二分找到第一个大于 Ai​的位置 p

    • 则 k=p(下标从0开始)

    • S≤​=prefp

    • 代入公式计算贡献

  4. 累加所有贡献,取模输出

4. 时间复杂度

  • 排序:O(MlogM)

  • 二分查找:O(NlogM)

  • 总复杂度:O((N+M)logM),可行

5. 取模处理

模数 MOD=998244353,注意:

  • 所有加减乘都要取模

  • 处理负数:(x % MOD + MOD) % MOD

    #include <bits/stdc++.h>
    using namespace std;
    const int MOD = 998244353;

    int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    复制代码
      int N, M;
      cin >> N >> M;
      
      vector<long long> A(N), B(M);
      for (int i = 0; i < N; i++) cin >> A[i];
      for (int i = 0; i < M; i++) cin >> B[i];
      
      // 1. 对B排序
      sort(B.begin(), B.end());
      
      // 2. 计算B的前缀和(模MOD)
      vector<long long> pref(M + 1, 0);
      for (int i = 0; i < M; i++) {
          pref[i + 1] = (pref[i] + B[i]) % MOD;
      }
      
      long long total_B_sum = pref[M] % MOD;  // B的总和
      
      long long ans = 0;
      
      // 3. 对每个A[i]计算贡献
      for (int i = 0; i < N; i++) {
          long long ai = A[i] % MOD;
          
          // 二分查找:第一个大于ai的位置
          int p = upper_bound(B.begin(), B.end(), ai) - B.begin();
          // p 就是小于等于ai的元素个数
          
          long long k = p;
          long long S_le = pref[p] % MOD;  // 小于等于ai的部分和
          
          // 贡献 = (2k - M) * ai + (total_B_sum - 2*S_le)
          long long term1 = ((2 * k - M) % MOD) * ai % MOD;
          long long term2 = (total_B_sum - 2 * S_le) % MOD;
          
          long long contribution = (term1 + term2) % MOD;
          ans = (ans + contribution) % MOD;
      }
      
      // 处理负数
      ans = (ans % MOD + MOD) % MOD;
      cout << ans << "\n";
      
      return 0;

    }

相关推荐
罗湖老棍子1 小时前
【例 1】Sightseeing Trip(信息学奥赛一本通- P1494)(洛谷-P10927)
数据结构·算法·图论·最短路·floyd·最小环
努力实干2 小时前
面向对象设计原则——C++
开发语言·c++·数码相机
stsdddd3 小时前
YOLO算法建筑工地安全帽目标检测数据集16881张:标注核对笔记
算法·yolo·目标检测
CV爱数码4 小时前
论文精读|Learned Primal-Dual:把原始–对偶算法展开成网络
图像处理·算法·计算机视觉·ct·重建·断层扫描
yuniko-n4 小时前
【算法】约瑟夫环问题
java·算法
郝亚军4 小时前
manifest 中 `sha256` 与 `signValue` 的作用
java·开发语言·数据结构
syagain_zsx4 小时前
jsoncpp 使用指南:编译链接、Json::Value 取值与高频坑
c++·json·库·http格式
l1t5 小时前
测试DuckDB v2.1.0-alpha49002的bignum乘法
数据库·sql·算法·duckdb
Swilderrr5 小时前
论文精读:《Directory-Aware Query and Maintenance in Vector Databases》
笔记·学习
SatanII5 小时前
K8s 存储与配置管理|Volume、ConfigMap、Secret 核心笔记
笔记·rpc·kubernetes