zoukankan      html  css  js  c++  java
  • 2018山东省赛 E Sequence ( 思维 )

    题目链接

    题意 : 给出一个排列,让你删除一个数,使得删除后整个序列的 Good 数数量最多。Good 数的定义为 若 Ai 为 Good 则存在 Aj < Ai ( j < i )

    分析 : 

    画画几个规律就能得出如下几个结论

    ① 若删除一个 Good 数,则原序列 Good 数的数量只会减一,即只会影响到这个 Good 数本身

    这个也不难证明,若 Ai 是 Good 数,则存在  Aj < Ai ( j < i )

    考虑当前有 Good 数 Ak 因删除 Ai 而变成非 Good 数,这个显然是不成立的

    因为 Ai 是 Good 数的前提是存在 Aj 而 Aj 的存在就已经能够保证 Ak 是 Good 数了

    故没有除了 Ai 以外的 Good 数因为 Ai 的删除被影响

    ② 如果一个数是非 Good 数,则这个数一定是从第一个数到这个数为止最小的数

    ③ 若删除的是一个非 Good 数,则去考虑有哪几个数因此被影响,即从 Good 变成 非 Good

    删除一个非 Good 数那么影响到的只可能是其右边的数

    那么考虑哪些数会因为这个数被删除就直接变成非 Good 数呢?

    根据 ② 知道从头开始到这个非 Good 数,这个非 Good 数是最小的数

    那么从这个非 Good 数开始向右延伸,如果右边的数是从头开始算起第二小的数

    即它只比这个非 Good 数大的话,那么一旦删除这个非 Good 数,这个第二小的数必定变成非 Good

    举个例子 1 4 3 2 这个排列,对于 4 其是从 1 开始算起第二小的数,如果 1 这个非 Good 数被删除

    则 4 将变成非 Good ,而 3、2 同理,所以删除 1 必将影响 3 个数

    那么到现在为止,算法就可以基本成型了

    删除一个 Good 数原数列减少一个 Good 数

    删除一个非 Good 我们可以预处理前缀最值和次大值来统计每个非 Good 的删除影响

    最后选出代价最小且相同代价下最小的数即可

    #include<bits/stdc++.h>
    #define LL long long
    #define ULL unsigned long long
    
    #define scs(i) scanf("%s", i)
    #define sci(i) scanf("%d", &i)
    #define scd(i) scanf("%lf", &i)
    #define scl(i) scanf("%lld", &i)
    #define scIl(i) scanf("%I64d", &i)
    #define scii(i, j) scanf("%d %d", &i, &j)
    #define scdd(i, j) scanf("%lf %lf", &i, &j)
    #define scll(i, j) scanf("%lld %lld", &i, &j)
    #define scIll(i, j) scanf("%I64d %I64d", &i, &j)
    #define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
    #define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
    #define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
    #define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
    
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    #define lowbit(i) (i & (-i))
    #define mem(i, j) memset(i, j, sizeof(i))
    
    #define fir first
    #define sec second
    #define ins(i) insert(i)
    #define pb(i) push_back(i)
    #define pii pair<int, int>
    #define mk(i, j) make_pair(i, j)
    #define pll pair<long long, long long>
    using namespace std;
    const int maxn = 1e6 + 10;
    const int INF = 0x3f3f3f3f;
    int Min1[maxn], Min2[maxn], arr[maxn], cnt[maxn];
    bool isGood[maxn];
    int n, nCase;
    
    int main(void)
    {
        sci(nCase);
        while(nCase--){
    
            mem(isGood, true);
    
            sci(n);
            for(int i=1; i<=n; i++) sci(arr[i]);
    
            int MM1 = INF, MM2 = INF;
            for(int i=1; i<=n; i++){
    
                if(arr[i] < MM1){
                    MM2 = MM1;
                    MM1 = arr[i];
                }else if(arr[i] < MM2) MM2 = arr[i];
    
                Min1[i] = MM1, Min2[i] = MM2;
    
                if(arr[i] == MM1) isGood[i] = false;
            }
    
            int idx;
            for(int i=1; i<=n; i++){
                if(!isGood[i]){
                    idx = i;
                    cnt[i] = 0;
                }else if(arr[i] == Min2[i]) cnt[idx]++;
            }
    
            int ans = INF;
            for(int i=1; i<=n; i++){///如果是非 Good 而且删除还没任何影响
                if(!isGood[i] && cnt[i] == 0){ ///则选出最小的这种数作为答案。
                    ans = min(ans, arr[i]);
                }
            }
    
            if(ans == INF){
                for(int i=1; i<=n; i++){
                    if(!isGood[i] && cnt[i] == 1) ans = min(ans, arr[i]);
                    else if(isGood[i]) ans = min(ans, arr[i]);
                }
            }
    
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    字符串内部查找函数
    vs2005 编译zlib 1.2.3 小记
    ies4linux 安装
    详述IP数据包的转发流程
    看源代码
    091213
    值得你记住并受用一生的Word XP/2003快捷键
    java开源框架的源代码怎么读?
    excel中的EMBED域介绍
    如何用c语言实现CString的构造函数、析构函数和赋值函数?
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/9074460.html
Copyright © 2011-2022 走看看