Contest3620 - 【在线编程平台】2024小学期程序设计实训竞-赛-班专题训练一(STL专题、思维专题、贪心专题)

问题G: 还差三道题就编完了的第八题

题目描述
给定一个数组,你可以在它重新排列之后,求得它的 正向的严格最长上升子序列的长度反向的严格最长上升子序列的长度 两者取最小值

求这个最小值最大是多少.

输入格式
第一行输入一个数字 t t t,表示有 t t t组数据 ( 1 ≤ t ≤ 10000 ) (1\leq t \leq 10000) (1t10000)
每组数据第一行输入一个数 n n n,表示数组的长度 n n n ( 1 ≤ n ≤ 200000 ) (1\leq n \leq 200000) (1n200000)
接下来输入 n n n个数 a [ i ] a[i] a[i] ( 1 ≤ a [ i ] ≤ 1 e 9 ) (1\leq a[i] \leq 1e9) (1a[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[n1]放在左边的上升子序列, a [ n − 2 ] a[n-2] a[n2]放在右边的下降子序列, a [ n − 3 ] a[n-3] a[n3]放在左边序列,一直重复

假设数组没有重复的数,答案为 ( 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值