欢迎光临
我们一直在努力

天梯赛编程题 L3-041 影响力 题解

天梯赛编程题 L3-041 影响力 题解

题面如下:
题面
根据题面和简单的逻辑思维可以很快想出一种题解

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);

int n, m;
cin >> n >> m;

vector<vector<ll>> grid(n, vector<ll>(m));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> grid[i][j];
}
}

for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
ll current_strength = grid[i][j];
ll total_cost = 0;

for (int k = 0; k < n; ++k) {
for (int l = 0; l < m; ++l) {
if (i == k && j == l) continue;

int dist = max(abs(i k), abs(j l));

total_cost += current_strength * dist;
}
}

cout << total_cost << (j == m 1 ? "" : " ");
}
cout << "\\n";
}

return 0;
}

此题解非常易于理解 但是时间复杂度达到了O((nm)2)
在算法比赛中一定会TLE
所以接下来我们需要思考一种时间复杂度更低的算法
最简单的暴力算法降低时间复杂度的方式就是前缀和与差分!

算法思路:高效计算影响力总代价

1. 问题建模

核心公式

一个国家 AAA 影响另一个国家 BBB 的代价定义为:
CAB=SA×dist(A,B) C_{AB} = S_A \\times dist(A, B) CAB=SA×dist(A,B)

其中,距离 dist(A,B)dist(A, B)dist(A,B) 为切比雪夫距离(Chebyshev distance):
dist(A,B)=max⁡(∣iA−iB∣,∣jA−jB∣) dist(A, B) = \\max(|i_A – i_B|,|j_A – j_B|) dist(A,B)=max(iAiBjAjB)
这里 (iA,jA)(i_A, j_A)(iA,jA)(iB,jB)(i_B, j_B)(iB,jB) 分别是国家 AAA 和国家 BBB 在矩阵中的行号和列号(从 1 开始)。

目标函数

对于矩阵中的每一个位置 (i,j)(i, j)(i,j),我们需要计算它对所有其他位置 (k,l)(k, l)(k,l) 的影响代价之和:
TotalCost(i,j)=∑(k,l)≠(i,j)C(i,j)(k,l)=∑(k,l)≠(i,j)S(i,j)×dist((i,j),(k,l)) TotalCost_{(i,j)} = \\sum_{(k,l) \\neq (i,j)} C_{(i,j)(k,l)} = \\sum_{(k,l) \\neq (i,j)} S_{(i,j)} \\times dist((i,j), (k,l)) TotalCost(i,j)=(k,l)=(i,j)C(i,j)(k,l)=(k,l)=(i,j)S(i,j)×dist((i,j),(k,l))

提取公因子 S(i,j)S_{(i,j)}S(i,j)
TotalCost(i,j)=S(i,j)×∑(k,l)≠(i,j)dist((i,j),(k,l))⏟D(i,j) TotalCost_{(i,j)} = S_{(i,j)} \\times \\underbrace{\\sum_{(k,l) \\neq (i,j)} dist((i,j), (k,l))}_{D_{(i,j)}} TotalCost(i,j)=S(i,j)×D(i,j)(k,l)=(i,j)dist((i,j),(k,l))

关键结论:问题的核心转化为高效计算任意点 (i,j)(i, j)(i,j) 到矩阵中所有其他点的距离之和 D(i,j)D_{(i,j)}D(i,j)。最终答案即为 S(i,j)×D(i,j)S_{(i,j)} \\times D_{(i,j)}S(i,j)×D(i,j)


2. 复杂度分析与优化方向

  • 暴力解法:直接对每个点遍历整个矩阵计算距离和。
    • 时间复杂度:O((nm)2)O((nm)^2)O((nm)2)
    • 瓶颈:若 n=1000,m=1000n=1000, m=1000n=1000,m=1000,运算次数达 101210^{12}1012,必然超时(TLE)。
  • 优化目标:利用数学性质将单次计算复杂度降至 O(1)O(1)O(1),使总复杂度降为 O(nm)O(nm)O(nm)

3. 数学推导与前缀和思想

区域分解

对于固定点 (r,c)(r, c)(r,c),总距离和可以分解为四个象限区域的贡献:
∑i=1n∑j=1mmax⁡(∣r−i∣,∣c−j∣) \\sum_{i=1}^{n} \\sum_{j=1}^{m} \\max(|r-i|,|c-j|) i=1nj=1mmax(ricj)

由于对称性,我们只需解决一个通用子问题:计算矩形区域 ∑max⁡(x,y)\\sum \\max(x, y)max(x,y) 的和。

以右下方区域为例(即 i≥r,j≥ci \\ge r, j \\ge cir,jc):
x=i−rx = i – rx=ir, y=j−cy = j – cy=jc,则需计算:
∑x=0X∑y=0Ymax⁡(x,y) \\sum_{x=0}^{X} \\sum_{y=0}^{Y} \\max(x, y) x=0Xy=0Ymax(x,y)
其中 X=n−rX = n – rX=nr, Y=m−cY = m – cY=mc

分类讨论

将求和区域分为两部分:

  • x≥yx \\ge yxy 时:max⁡(x,y)=x\\max(x, y) = xmax(x,y)=x
    • 求和项:∑x=0X∑y=0min⁡(x,Y)x\\sum_{x=0}^{X} \\sum_{y=0}^{\\min(x, Y)} xx=0Xy=0min(x,Y)x
  • y>xy > xy>x 时:max⁡(x,y)=y\\max(x, y) = ymax(x,y)=y
    • 求和项:∑y=1Y∑x=0min⁡(y−1,X)y\\sum_{y=1}^{Y} \\sum_{x=0}^{\\min(y-1, X)} yy=1Yx=0min(y1,X)y
  • 通过等差数列求和公式推导,可得闭合形式解。


    4. 核心函数 calc_sum(X, Y)

    定义函数 calc_sum(X, Y) 用于计算 ∑x=0X∑y=0Ymax⁡(x,y)\\sum_{x=0}^{X} \\sum_{y=0}^{Y} \\max(x, y)x=0Xy=0Ymax(x,y)

    计算公式

    假设 X≥YX \\ge YXY(若 X<YX < YX<Y,利用对称性交换参数):

    calc_sum(X,Y)=Y⋅(Y+1)⋅(3X−Y+1)6+(X−Y)⋅(X−Y+1)⋅(2X+Y+2)6
    \\begin{align*}
    \\text{calc\\_sum}(X, Y) &= \\frac{Y \\cdot (Y+1) \\cdot (3X – Y + 1)}{6} \\\\
    &\\quad + \\frac{(X-Y) \\cdot (X-Y+1) \\cdot (2X + Y + 2)}{6}
    \\end{align*}
    calc_sum(X,Y)=6Y(Y+1)(3XY+1)+6(XY)(XY+1)(2X+Y+2)

    • 第一项:对应 y>xy > xy>x 部分及 x≥yx \\ge yxyx≤Yx \\le YxY 部分的贡献。
    • 第二项:对应 x≥yx \\ge yxyx>Yx > Yx>Y 部分的贡献。

    5. 最终算法流程

    对于矩阵中任意点 (r,c)(r, c)(r,c),其总距离和 D(r,c)D_{(r,c)}D(r,c) 由四个方向的 calc_sum 累加得到:

    D(r,c)=calc_sum(r−1,c−1)+calc_sum(r−1,m−c)+calc_sum(n−r,c−1)+calc_sum(n−r,m−c)
    D_{(r,c)} = \\mathrm{calc\\_sum}(r-1, c-1) + \\mathrm{calc\\_sum}(r-1, m-c) + \\mathrm{calc\\_sum}(n-r, c-1) + \\mathrm{calc\\_sum}(n-r, m-c)
    D(r,c)=calc_sum(r1,c1)+calc_sum(r1,mc)+calc_sum(nr,c1)+calc_sum(nr,mc)

    其中:

    • calc_sum(r−1,c−1)\\mathrm{calc\\_sum}(r-1, c-1)calc_sum(r1,c1) → 左上区域
    • calc_sum(r−1,m−c)\\mathrm{calc\\_sum}(r-1, m-c)calc_sum(r1,mc) → 右上区域
    • calc_sum(n−r,c−1)\\mathrm{calc\\_sum}(n-r, c-1)calc_sum(nr,c1) → 左下区域
    • calc_sum(n−r,m−c)\\mathrm{calc\\_sum}(n-r, m-c)calc_sum(nr,mc) → 右下区域

    复杂度总结

    • 单次查询:O(1)O(1)O(1)(仅涉及常数次算术运算)。
    • 总时间复杂度:O(nm)O(nm)O(nm)(遍历矩阵每个点一次)。
    • 空间复杂度:O(1)O(1)O(1)(若不存储输入矩阵)或 O(nm)O(nm)O(nm)(存储输入)。

    该算法完全满足 nm≤106nm \\le 10^6nm106 的数据规模限制。

    #include <iostream>
    #include <vector>
    #include <algorithm>

    using namespace std;

    typedef long long ll;

    ll calc_sum(ll X, ll Y) {
    if (X < 0 || Y < 0) return 0;
    if (X < Y) swap(X, Y);

    ll term1 = Y * (Y + 1) * (3 * X Y + 1) / 6;

    ll term2 = (X Y) * (X Y + 1) * (2 * X + Y + 2) / 6;

    return term1 + term2;
    }

    int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n, m;
    if (!(cin >> n >> m)) return 0;

    vector<vector<ll>> grid(n, vector<ll>(m));
    for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
    cin >> grid[i][j];
    }
    }

    for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {

    ll dist_sum = 0;

    dist_sum += calc_sum(i 1, j 1);

    dist_sum += calc_sum(i 1, m 1 j);

    dist_sum += calc_sum(n 1 i, j 1);

    dist_sum += calc_sum(n 1 i, m 1 j);

    ll total_cost = grid[i][j] * dist_sum;

    cout << total_cost << (j == m 1 ? "" : " ");
    }
    cout << "\\n";
    }

    return 0;
    }

    赞(0)
    未经允许不得转载:171主机测评 » 天梯赛编程题 L3-041 影响力 题解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址