Codeforces1637E Best Pair

tags

枚举 暴力

中文题面

给你一个长度为 n n n 的数组 a a a 。设 c n t x cnt_x cntx 是数组中等于 x x x 的元素个数。再将 f ( x , y ) f(x, y) f(x,y) 定义为 ( c n t x + c n t y ) ⋅ ( x + y ) (cnt_x + cnt_y) \cdot (x + y) (cntx+cnty)⋅(x+y) 。

此外,我们还得到了 m m m 个坏数对 ( x i , y i ) (x_i, y_i) (xi,yi) 。请注意,如果 ( x , y ) (x, y) (x,y) 是一对坏数组,那么 ( y , x ) (y, x) (y,x) 也是坏数组。

你的任务是在所有的 ( u , v ) (u, v) (u,v) 中找出 f ( u , v ) f(u, v) f(u,v) 的最大值,使得 u ≠ v u \neq v u=v 这一对不是坏的,并且 u u u 和 v v v 都出现在数组 a a a 中。可以保证存在这样的一对。
输入

第一行包含一个整数 t t t ( 1 ≤ t ≤ 10 , 000 1 \le t \le 10,000 1≤t≤10,000 )--测试用例数。

每个测试用例的第一行包含两个整数 n n n 和 m m m ( 2 ≤ n ≤ 3 ⋅ 1 0 5 2 \le n \le 3 \cdot 10^5 2≤n≤3⋅105 , 0 ≤ m ≤ 3 ⋅ 1 0 5 0 \le m \le 3 \cdot 10^5 0≤m≤3⋅105 )--数组的长度和坏对的数量。

每个测试用例的第二行包含 n n n 个整数 a 1 , a 2 , ... , a n a_1, a_2, \ldots, a_n a1,a2,...,an ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1≤ai≤109 )。( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1≤ai≤109 ) - 数组元素。

接下来的 m m m 行的 i i i -th 包含两个整数 x i x_i xi 和 y i y_i yi ( 1 ≤ x i < y i ≤ 1 0 9 1 \le x_i \lt y_i \le 10^9 1≤xi<yi≤109 ),这两个整数代表一对坏数组。保证输入中不会出现两次坏对。同时也保证 c n t x i > 0 cnt_{x_i} > 0 cntxi>0 和 c n t y i > 0 cnt_{y_i} > 0 cntyi>0 。

保证每个测试用例中都有一对整数 ( u , v ) (u, v) (u,v) , u ≠ v u \ne v u=v 不是坏数,而且这两个数字都出现在 a a a 中。

保证 n n n 和 m m m 的总和不超过 3 ⋅ 1 0 5 3 \cdot 10^5 3⋅105 。

思路

经过半天的转化发现题目给定的式子没有什么很好的转化方法,我们还是把它保持原样,设想我们现在枚举 c n t x cnt_x cntx 和 c n t y cnt_y cnty,此时要让 f ( x , y ) f(x, y) f(x,y) 最大只需要选计数为 c n t x cnt_x cntx 中最大的数作为 x x x 和计数为 c n t y cnt_y cnty 中最大的数作为 y y y,考虑在这个数组中有多少种不同的计数,假设有 k k k 种,那最多种的情况是 1 + 2 + . . . + k = n 1+2+...+k=n 1+2+...+k=n,由等差数列可知 k ≈ √ n k≈√n k≈√n,那么枚举 c n t x cnt_x cntx c n t y cnt_y cnty 只需要 n n n 的复杂度,每次找出的最大的 x x x y y y 应该排除掉坏数对,而这种排除最多进行 m m m 次。最后为了只枚举出现过的 c n t x cnt_x cntx 和 c n t y cnt_y cnty 使用 m a p map map,总时间复杂度 O ( ( n l o g √ n + m ) l o g m ) O((nlog√n+m)logm) O((nlog√n+m)logm)

代码

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define N (int)3e5 + 5
#define pdd pair<double, double>
#define pii pair<int, int>

int a, b, c, d, x, y, n, m, t, k, q, l, r, p, z, h;
int num[N];
string s;
map<int, int> cnt;
map<pii, int> bad;
map<int, vector<int>> mp;
vector<int> all;
signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	// 注意根据数据量调整N的大小
    cin >> t;
    while (t--) {
        cnt.clear();
        mp.clear();
        all.clear();
        bad.clear();
        cin >> n >> m;
        for (int i = 1; i <= n; i++) {
            cin >> x;
            cnt[x]++;
        }
        while (m--) {
            cin >> x >> y;
            bad[{x,y}] = bad[{y,x}] = 1;
        }
        for (auto it = cnt.begin(); it != cnt.end(); it++) {
            mp[it->second].push_back(it->first);
            all.push_back(it->second);
        }
        for (auto it = mp.begin(); it != mp.end(); it++) sort(it->second.begin(), it->second.end());
        sort(all.begin(), all.end());
        int len = unique(all.begin(), all.end()) - all.begin();
        int mx = -1e18;
        for (int i = 0; i < len; i++) {
            for (int j = i + 1; j < len; j++) {
                auto& lv = mp[all[i]];
                auto& rv = mp[all[j]];
                int f = 0;
                for (l = lv.size() - 1; l >= 0; l--) {
                    for (r = rv.size() - 1; r >= 0; r--) {
                        if (bad.count({lv[l], rv[r]}) || bad.count({rv[r], lv[l]})) continue;
                        mx = max(mx, (all[i]+all[j])*(lv[l]+rv[r]));
                        if (r == rv.size() - 1) f = 1;
                        break;
                    }
                    if (f) break;
                }
            }
            // j == i单独
            int f = 0;
            auto& v = mp[all[i]];
            for (l = v.size() - 1; l >= 0; l--) {
                for (r = l - 1; r >= 0; r--) {
                    if (bad.count({v[l], v[r]}) || bad.count({v[r], v[l]})) continue;
                    mx = max(mx, (all[i]+all[i])*(v[l]+v[r]));
                    if (r == l - 1) f = 1;
                    break;
                }
                if (f) break;
            }
        }
        cout << mx << '\n';
    }
	return 0;
}
相关推荐
Dizzy.5173 小时前
数据结构(查找)
数据结构·学习·算法
专注VB编程开发20年5 小时前
除了 EasyXLS,加载和显示.xlsx 格式的excel表格,并支持单元格背景色、边框线颜色和粗细等格式化特性
c++·windows·excel·mfc·xlsx
分别努力读书6 小时前
acm培训 part 7
算法·图论
武乐乐~6 小时前
欢乐力扣:赎金信
算法·leetcode·职场和发展
'Debug6 小时前
算法从0到100之【专题一】- 双指针第一练(数组划分、数组分块)
算法
Fansv5876 小时前
深度学习-2.机械学习基础
人工智能·经验分享·python·深度学习·算法·机器学习
夏天的阳光吖6 小时前
C++蓝桥杯基础篇(四)
开发语言·c++·蓝桥杯
oioihoii7 小时前
C++17 中的 std::to_chars 和 std::from_chars:高效且安全的字符串转换工具
开发语言·c++
张胤尘7 小时前
C/C++ | 每日一练 (2)
c语言·c++·面试
強云8 小时前
23种设计模式 - 装饰器模式
c++·设计模式·装饰器模式