【习题 8-16 UVA - 1618】Weak Key

【链接】 我是链接,点我呀:)
【题意】


在这里输入题意

【题解】


枚举N[q]和N[r]的位置
因为N[q]是最大值,且N[r]是最小值。
且它们是中间的两个。
枚举这两个可以做到不重复枚举。

然后假设我们枚举了q和r的位置分别为i和j
(a[i]>a[j]
那么我们接下来需要得到两个东西。
1.在j的右边找到一个尽可能大的且小于a[i]的数字dp[0][i][j];
2.在i的左边找到一个尽可能小且大于a[j]的数字dp[1][i][j]。
然后判断一下dp[0][i][j]> a[j] && dp[1][i][j]< a[i] && dp[0][i][j] > dp[1][i][j]
是否成立就好

还要考虑a[i]<a[j]的情况(有两种情况之一成立都是弱键。
方便起见。
直接把原数组翻转一下。
就会发现用上面说的思路重新做一遍就可以了。

dp[0..1][i][j]这两个数组可以用一个set.在\(O(N^2*log_2N)\)的复杂度下得到。

【代码】

/*
    dp1[i][j] 表示 j右边 大于a[j]且小于a[i]的
    最大数字
        ->小于a[i]的最大数字

    dp2[i][j] 表示i左边 大于a[j]且最小的数字

    for (int j = n;j >= 1;j--){

    }
*/
#include <bits/stdc++.h>
#define ll long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define all(x) x.begin(),x.end()
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1
using namespace std;

const double pi = acos(-1);
const int dx[4] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0};
const int N = 5e3;

set<int> myset;
int n,a[N+10],dp[2][N+10][N+10];

bool solve(){
    myset.clear();
    rep2(j,n,1){
        rep2(i,j-1,1)
            if (a[i]>a[j]){
                auto temp = myset.upper_bound(a[i]);
                if (temp==myset.begin()) {
                    dp[0][i][j] = 0;
                    continue;
                }
                temp--;
                dp[0][i][j] = (*temp);
            }
        myset.insert(a[j]);
    }
    myset.clear();
    rep1(i,1,n){
        rep1(j,i+1,n)
            if (a[i]>a[j]){
                auto temp = myset.upper_bound(a[j]);
                if (temp==myset.end()) {
                    dp[1][i][j] = 0;
                    continue;
                }
                dp[1][i][j] = (*temp);
            }
        myset.insert(a[i]);
    }
    rep1(i,1,n)
        rep1(j,i+1,n)
            if (a[i]>a[j]){
                if (dp[0][i][j]==0 || dp[1][i][j]==0) continue;
                if (dp[0][i][j]>a[j] && dp[1][i][j]<a[i] &&
                    dp[0][i][j]>dp[1][i][j]){
                        return true;
                    }
            }
    return false;
}

int main(){
    #ifdef LOCAL_DEFINE
        freopen("rush_in.txt", "r", stdin);
    #endif
    ios::sync_with_stdio(0),cin.tie(0);
    int T;
    cin >> T;
    while (T--){
        cin >> n;
        rep1(i,1,n) cin >> a[i];
        if (solve()){
            cout<<"YES"<<endl;
            continue;
        }
        reverse(a+1,a+1+n);
        if (solve()){
            cout<<"YES"<<endl;
            continue;
        }
        cout<<"NO"<<endl;
    }
    return 0;
}

转载于:https://www.cnblogs.com/AWCXV/p/8455727.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值