题意很简单,就是枚举每个颜色的每个点,然后计算两点间的距离并加和
可知行和列是独立的,可以进行独立求和运算,所以就先单独考虑如何求行,先把行数按从小到大进行排序
考虑在左式中对于s1,s2...sk-1出现过几次,根据求和式,不难发现sj出现j次,在右式中si出现k-1-i次,然后两式合并,就可以得出si的贡献是多少,这样可以避免重复的运算,按列求同理
AC代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize("Ofast") #include<bits/stdc++.h> // #include <iostream> // #include <cstdio> // #include <queue> // #include <deque> // #include <stack> // #include <string> // #include <cstring> // #include <numeric> // #include <functional> // #include <cstdlib> // #include <vector> // #include <set> // #include <map> // #include <algorithm> // #include <cmath> // #include <iomanip> using i64 = long long; using namespace std; #define lowbit(x) ((x) & -(x)) #define endl '\n' #define IOS1 ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr); #define IOS2 ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); typedef vector<int> vi; typedef vector<long long> vll; typedef vector<char> vc; typedef long long ll; // typedef long long i64; template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; } template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; } template<class T> T power(T a, int b) { T res = 1; for (; b; b >>= 1, a = a * a) { if (b & 1) { res = res * a; } } return res; } template <typename T> T Myabs(T a) { return a >= 0 ? a : -a; } template <typename T> inline void read(T& x) { x = 0; int f = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); } while (isdigit(ch)) { x = x * 10 + ch - '0', ch = getchar(); } x *= f; } const int INF = 0x3f3f3f3f; // const int mod = 1000000007; const int mod = 998244353; const double PI = acos(-1.0); const double eps = 1e-6; inline int sgn(double x) { return x < -eps ? -1 : x > eps; } /* Tips: 1.int? long long? 2.don't submit wrong answer 3.figure out logic first, then start writing please 4.know about the range 5.check if you have to input t or not 6.modulo of negative numbers is not a%b, it is a%b + abs(b) */ void solve() { int n, m; cin >> n >> m; map<int, vector<int>> xx, yy; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { int x; cin >> x; xx[x].push_back(i); yy[x].push_back(j); } } auto calc = [&](auto s) { i64 sum = 0; for (auto [i, j] : s) { sort(j.begin(), j.end()); i64 cnt = 0; i64 sz = j.size(); for (auto it : j) { sum += ((cnt << 1) + 1 - sz) * it; cnt++; } } return sum; }; i64 ans = calc(xx) + calc(yy); cout << ans << endl; return; } signed main() { IOS1; // IOS2; #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); #endif int __t = 1; // cin >> __t; for (int _t = 1; _t <= __t; _t++) { solve(); } return 0; } /* */
这种计算贡献度的题还是要好好理解清楚如何计算的这个过程
Weird Sum(贡献度计算+化简公式)
最新推荐文章于 2024-03-29 17:49:31 发布