第九届山东省赛E题 Sequence II 【思维题】

本文针对SequenceII算法问题提供了解决方案,目标是在给定整数序列中移除一个元素以最大化good元素的数量,并输出代价最小的移除选项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6990: Sequence II

时间限制: 3 Sec   内存限制: 128 MB
提交: 201   解决: 22
[ 提交][ 状态][ 讨论版][命题人: admin]

题目描述

We define an element ai in a sequence "good", if and only if there exists a j(1≤ j < i) such that aj < ai.
Given a permutation p of integers from 1 to n. Remove an element from the permutation such that the number of "good" elements is maximized.

输入

The input consists of several test cases. The first line of the input gives the number of test cases, T(1≤ T≤ 10^3).
For each test case, the first line contains an integer n(1≤ n≤ 10^6), representing the length of the given permutation.
The second line contains n integers p1,p2,\cdots,pn(1≤ pi≤ n), representing  the given permutation p.
It’s guaranteed that Σn≤ 2× 10^7.

输出

For each test case, output one integer in a single line, representing the element that should be deleted. If there are several answers, output the minimal one.

样例输入

2
1
1
5
5 1 2 3 4

样例输出

1
5

题意:

给你一串序列,对于其中的一个数ni如果存在一个nj (1<=j<i) 使得ni>nj  那么ni就是一个good数

问你如果一定要去掉一个数,去掉哪个数会使整个序列的good数最大化。如果存在多个这样的数,输出最小的那个。


思路:

经过演算我们得知,无论去掉哪个数,good数都不会增加。所以这题转换为去掉那个数会让总序列的good数减少最少。

我们需要计算出每一个数被去掉后,good数减少的数目。作为去掉这个数的“代价” 我们需要选取代价最少的数去掉。


为此,我们需要维护一个前缀序列的最小值与次小值。如果一个数大于他前缀(这个数之前的序列,不包含该数)序列的最小值,但是小于次小值。那么如果我们去掉这个最小值,那么这个数就不再是一个good数。所以去掉这个最小值的代价值就要增加1。如果一个数本身是一个good数,那该数的代价也要加一。


还有这题需要用输入外挂·输入,否则会直接超时、


#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define M(a,b) memset(a,b,sizeof(a))
const int MAXN = 1e6+5;
const int INF = 0x3f3f3f3f;
int n;
int num[MAXN];
int vis[MAXN];///记录代价值
int zx,cx,zxi,cxi;///zx是最小值。cx是次小值,zxi是最小值的下标。cxi是次小值的下标。
int read()///输入外挂
{
    char c;
    int ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9')
    {
        ret = ret * 10 + (c - '0'), c = getchar();
    }
    return ret;
}
int main()
{
    int T;
    T = read();
    while(T--)
    {
        M(vis,0);
        n = read();

        for(int i=0; i<n; i++)  num[i] = read();
        zx = INF;
        cx = INF;
        zxi=0;
        cxi=0;
        for(int i=0;i<n;i++)
        {
            if(num[i]>cx)///与次小值比较
            {
                vis[i]++;
            }
            else if(num[i]>zx)///如果大于最小值且小于次小值
            {
                vis[i]++;
                vis[zxi]++;///最小值的代价增加
            }
            if(num[i]<zx)///小于最小值,更新最小值与次小值。
            {
                cx = zx;
                cxi = zxi;
                zx = num[i];
                zxi = i;
            }
            else if(num[i]<cx)///只小于次小值,更新次小值。
            {
                cx = num[i];
                cxi = i;
            }

        }
       // for(int i=0; i<n; i++) printf("vis[%d]==%d\n",i,vis[i]);
        int M1 = vis[0];
        int M2 = num[0];
        for(int i=1; i<n; i++)
        {
            if(vis[i]<M1)///选取代价最小
            {
                M1=vis[i];
                M2=num[i];
            }
            if(vis[i]==M1&&num[i]<M2)///代价相等,取数小的。
            {
                M2 = num[i];
            }
        }
        printf("%d\n",M2);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值