【习题 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

时间: 2024-10-28 21:53:43

【习题 8-16 UVA - 1618】Weak Key的相关文章

UVa - 1618 - Weak Key

Cheolsoo is a cryptographer in ICPC(International Cryptographic Program Company). Recently, Cheolsoo developed a cryptographic algorithm called ACM(Advanced Cryptographic Method). ACM uses a key to encrypt a message. The encrypted message is called a

UVA - 1618 Weak Key(RMQ算法)

题目: 给出k个互不相同的证书组成的序列Ni,判断是否存在4个证书Np.Nq.Nr.Ns(1≤p<q<r<s≤k)使得Nq>Ns>Np>Nr或者Nq<Ns<Np<Nr. 思路: 有两种情况<小.最大.最小.大>.<大.最小.最大.小>,枚举第1个和第4个数,用RMQ查询这两个数之间的最大值和最小值,然后根据给出的条件判断一下就可以了. 看到好多大佬不用RMQ也写出来了,还需要在研究一下. 代码: #include <bit

1618 - Weak Key

一开始自己搞,写了半天还是成了四重循环,虽然没个循环依次递减,而且二分查找,但是依然超时,唉,看来还是太弱啊,思路过于单一. 搜了一个题解,是用递推构造了两个二维数组,利用题目的特点维护了两个变量,然后只需要枚举q和r就可以了. l[i][j]表示下标小于j且值比a[i]大的数中最小的值的下标. r[i][j]表示下标大于j且值比a[i]小的数中最大的值的下标. 我们枚举q和r ,那么显然可以利用r[i][j]找到下标比r大的且值比a[q]小的最大值,也就是s 同理可以用l[i][j]找到p,而

[詹兴致矩阵论习题参考解答]习题4.16

16. (Fan-Hoffman) 设 $A\in M_n$, $A=UP$ 为极分解, $U$ 为酉矩阵, $P$ 为半正定矩阵. 若 $W\in M_n$ 为酉矩阵, 则 $$\bex \sen{A-U}\leq \sen{A-W}\leq \sen{A+U} \eex$$ 对任何酉不变范数成立. 证明: (1). 仅须证明: 对正定阵 $P$, 酉阵 $V$, 不等式 $$\bee\label{4_16_ineq} \sen{P-I}\leq \sen{P-V}\leq \sen{P+I}

Java50道经典习题-程序16 在控制台上打印九九乘法表

题目:输出9*9口诀.分析:利用双重for循环进行输出,分行与列考虑,共9行9列,i控制行,j控制列. 1 public class Prog16 { 2 public static void main(String[] args) { 3 for(int i=1;i<10;i++) { 4 for(int j=1;j<i+1;j++) { 5 System.out.print(j+"*"+i+"="+(j*i)+"\t");//使用

习题3-5 Puzzle UVA - 227

这题太能卡人了,都是输入输出卡的. 1.输入的5X5矩阵中,有时一行最后有多个空格和回车 2.输出格式中,每两个输出结果之间间隔一个空行,但是最后一个结果之后没有空行. 3.有时到第四位元素,直接不按空格,直接换行了. 其实思路很简单,先判断是否运动越界,如果是的话就输出无答案,如果没越界,就依次将空格和目标位置元素相互交换. 下面是AC代码,就是把这些小BUG修修补补改出来的,抛砖引玉吧. #include <bits/stdc++.h> #define N 7 #define M_N 10

SICP 习题 (2.16)解题总结:避免误差的区间计算系统

SICP 习题 2.16 问我们能不能设计一个没有问题的区间计算系统,可以避免习题2.14中的问题.题目还吓我们说这可能很难. 这一下就把我吓住了,你不是说很难吗,那就很难吧,我不会.呵呵

UVA - 12874 Blanket

UVA - 12874 Blanket 题意: 给你n个毯子,m个人,并给你每条毯子厚的部分的长度和该厚的部分出现的周期: 求盖了0--n 个毯子的人数. 代码: #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<map> #include<set> #include<

算法竞赛入门经典第二版第三章习题

写这个的原因是看到一位大神的习题答案总结,于是自己心血来潮也想写一个这个,目的主要是督促自己刷题吧,毕竟自己太弱了. 习题3-1 得分 UVa 1585 大致就是设置一个变量记录到当前为止的连续的O的数量,碰到X就变0,水题. #include<stdio.h> #include<ctype.h> #include<string.h> char s[90]; int main(void) { int length,n,sum,num; scanf("%d&qu