首先,一种极端情况是所有的点的权值都相同,那么此时每个点只能连一条边。答案为 ⌊2n⌋ 。
接下来,对于普通的情况,由于不允许出现 wx≤wy≤wz 的这样三个点有 x 连 y ,y 连 z 的情况。
所以考虑将这些数排序,然后分成两部分。
两部分数有绝对的大小关系。
两部分的大小分别为 cnta ,cntb ,满足集合 a 中的数都小于集合 b 的数。
那么答案为 cnta×cntb
时间复杂度:O(nlogn)
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; ++i) cin >> a[i];
sort(a.begin(), a.end());
long long ans = n / 2;
for (int i = 0; i < n; ++i) {
int j = i + 1;
while (j < n && a[j] == a[i]) j += 1;
// [0~j-1] 和 [j~n-1]
ans = max(ans, 1ll * j * (n - j));
i = j - 1;
}
cout << ans << "\n";
return 0;
}
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
static int N = 100000;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
TreeMap<Integer, Integer> map = new TreeMap<>();
for (int i = 0; i < n; i++) {
int x = in.nextInt();
map.put(x, map.getOrDefault(x, 0) + 1);
}
long ans = 0;
long cur = 0;
for (Integer value : map.values()) {
cur += value;
ans = Math.max(ans, (cur) * (n - cur));
}
if (map.size() == 1) {
System.out.println(n / 2);
} else {
System.out.println(ans);
}
}
}
n = int(input())
w = list(map(int, input().split()))
w.sort()
tmp = w[(n-1)//2]
a = n
b = 0
for i in range(n):
if w[i] == tmp:
a = min(a, i)
b = max(b, i+1)
if a==0 and b==n:
print(n//2)
else:
print(max(a*(n-a), b*(n-b)))
小红有 n 个点,第 i 个点的权值为 wi 。
现在,小红想要用这 n 个点建图。
但是建好的图要满足如果存在三个点 a,b,c ,有边 a-b 和边 b-c ,那么不能有 wa≤wb≤wc 。
现在,小红想问你,建好的图上最多可以有多少条边。
第一行,一个整数 n(2≤n≤105),表示点数。
第二行,n 个整数表示每个点的权值,第 i 个数为 wi(1≤wi≤105)
一个整数,表示建好的图上最多可以有多少条边。
输入
4
1 2 3 4
输出
4
说明
可以连 1-3, 2-3, 1-4 和 2-4 这四条边。