【题目描述】
有 n n n个点,每个点的点权为 a i a_i ai,你可以在任意两个点之间连边,最终连成的图需要满足:不存在任意的三个点,满足 a u ≤ a v ≤ a w a_u\le a_v\le a_w au≤av≤aw(非降序)且边 ( u , v ) (u,v) (u,v)和 ( v , w ) (v,w) (v,w)存在。求最多能连的边数。
【输入格式】
第一行一个整数 t ( 1 ≤ t ≤ 1 0 4 ) t(1\le t\le 10^4) t(1≤t≤104),表示测试样例的数量。
对于每组测试样例第一行输入一个整数 n ( 2 ≤ n ≤ 2 × 1 0 5 ) n(2\le n\le 2\times 10^5) n(2≤n≤2×105),表示点的数量。
第二行输入 n n n个整数 a 1 , a 2 , … , a n ( 1 ≤ a i ≤ 1 0 6 ) a_1,a_2,\dots ,a_n(1\le a_i\le 10^6) a1,a2,…,an(1≤ai≤106),表示每个点的权值。
数据保证每组测试用例中的 n n n的和不超过 2 × 1 0 5 2\times 10^5 2×105。
【输出格式】
对于每组测试用例,输出一行共一个整数,即连出的图的最大边数。
【输入样例】
4
4
2 2 3 1
6
5 2 3 1 5 2
12
7 2 4 9 1 4 6 3 7 4 2 3
4
1000000 1000000 1000000 1000000
【输出样例】
3
9
35
2
【说明/提示】
In the first test case, there can only be at most 3 edges in the graph. A possible construction is to connect ( 1 , 3 ) , ( 2 , 3 ) , ( 3 , 4 ) (1,3), (2,3), (3,4) (1,3),(2,3),(3,4). In the picture below the red number above node i i i is a i a_i ai.
The following list shows all such u , v , w u,v,w u,v,w that the edges ( u , v ) (u,v) (u,v) and ( v , w ) (v,w) (v,w) exist.
【分析】
假如某个点与权值严格大于它的点相连,那么这个点就不能再连接权值小于等于它的点,反之同理。
那么我们考虑将所有点分成两个集合 S 1 , S 2 S_1,S_2 S1,S2,其中 S 1 S_1 S1中的所有点(数量为 c 1 c_1 c1)权值均小于等于该集合中的最大值 v 1 v_1 v1, S 2 S_2 S2中的所有点(数量为 c 2 c_2 c2)权值均大于等于该集合中的最小值 v 2 v_2 v2,且 v 1 < v 2 v_1
注意,如果每个点权值都相同最优解只能按下图这样连边,答案为 ⌊ n / 2 ⌋ \lfloor n/2\rfloor ⌊n/2⌋。
【代码】
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 200010;
int a[N];
int n;
int main()
{
int T;
cin >> T;
while (T--)
{
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
sort(a, a + n);
if (a[0] == a[n - 1]) { cout << n / 2 << endl; continue; }
LL res = 0;
int idx = 0, cnt = 1; // cnt表示较小数集合中的元素数量
while (idx < n)
{
while (idx + 1 < n && a[idx + 1] == a[idx]) idx++, cnt++;
res = max(res, LL(idx + 1) * (n - idx - 1));
idx++, cnt++;
}
cout << res << endl;
}
return 0;
}