问题G: 还差三道题就编完了的第八题
题目描述
给定一个数组,你可以在它重新排列之后,求得它的 正向的严格最长上升子序列的长度 和 反向的严格最长上升子序列的长度 两者取最小值
求这个最小值最大是多少.
输入格式
第一行输入一个数字
t
t
t,表示有
t
t
t组数据
(
1
≤
t
≤
10000
)
(1\leq t \leq 10000)
(1≤t≤10000)
每组数据第一行输入一个数
n
n
n,表示数组的长度
n
n
n
(
1
≤
n
≤
200000
)
(1\leq n \leq 200000)
(1≤n≤200000)
接下来输入
n
n
n个数
a
[
i
]
a[i]
a[i]
(
1
≤
a
[
i
]
≤
1
e
9
)
(1\leq a[i] \leq 1e9)
(1≤a[i]≤1e9)
保证所有n的和不超过200000
输出格式
对于每个样例输出一个数,表示答案
将数组重新排列成如下形式
如图所示, a 1 a_1 a1开始数列递增,到达 i i i位置时到最高点 a [ i ] a[i] a[i],后数列开始下降,因此 a [ 1 ] ∼ a [ i ] a[1] \sim a[i] a[1]∼a[i] 是上升子序列, a [ i ] ∼ a [ n ] a[i]\sim a[n] a[i]∼a[n]是下降子序列,由题意要上升子序列长度和下降子序列长度都最大,则两者长度应尽可能接近
将 a a a排序, a [ n ] a[n] a[n]一定是最高点,然后将 a [ n − 1 ] a[n-1] a[n−1]放在左边的上升子序列, a [ n − 2 ] a[n-2] a[n−2]放在右边的下降子序列, a [ n − 3 ] a[n-3] a[n−3]放在左边序列,一直重复
假设数组没有重复的数,答案为 ( n + 1 ) / 2 (n+1)/2 (n+1)/2,如果有重复的数,这个重复的数只能算作两次(左边序列放一次这个数,右边序列放一次这个数)
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int a[N];
void solve(){
int n;cin>>n;
int ans=0,cnt=0;
map<int,int> mp;
for(int i=1;i<=n;i++){
cin>>a[i];
if(mp[a[i]]<2)
mp[a[i]]++;
}
for(auto [x,y]:mp){
if(y==2)ans++;
else{
cnt++;
}
}
ans+=(cnt+1)/2;
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--){
solve();
}
return 0;
}