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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37405320/article/details/80349475

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;
}



阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页