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 cipher text. In ACM, to decrypt a cipher text, the same key used in the encryption should be applied. That is, the encryption key and the decryption key are the same. So, the sender and receiver should
agree on a key before they communicate securely using ACM. Soon after Cheolsoo finished the design of ACM, he asked its analysis on security to Younghee who is a cryptanalyst in ICPC.

Younghee has an interest in breaking cryptosystems. Actually, she developed many attacking methods for well-known cryptographic algorithms. Some cryptographic algorithms have weak keys. When a message is encrypted with a weak key, the message can be
recovered easily without the key from the cipher text. So, weak key should not be used when encrypting a message. After many trials, she found the characteristic of weak keys in ACM. ACM uses a sequence of mutually distinct positive integers (N1N2,..., Nk) as
a key. Younghee found that weak keys in ACM have the following two special patterns:

There are four integers NpNqNrNs(1p < q < r < sk) in
the key such that
(1) Nq > Ns > Np > Nr or Nq < Ns < Np < Nr

For example, the key (10, 30, 60, 40, 20, 50) has the pattern in (1); (_, 30, 60, _, 20, 50). So, the key is a weak key in ACM. But, the key (30, 40, 10, 20, 80, 50, 60, 70) is not weak because it does not have
any pattern in the above.

Now, Younghee wants to find an efficient method to determine, for a given key, whether it is a weak key or not. Write a program that can help Younghee.

Input

The input consists of T test cases. The number of test cases T is given in the first line of the input file. Each test case starts with a line
containing an integer k, the length of a sequence repressenting a key, 4k5,
000. In the next line, k mutually distinct positive integers are given. There is a single space between the integers, and the integers are between 1 and 100,000, both inclusive.

Output

Print exactly one line for each test case. Print `YES' if the sequence is a weak key. Otherwise, print `NO'.

The following shows sample input and output for three test cases.

Sample Input

3
6
10 30 60 40 20 50
8
30 40 10 20 80 50 60 70
4
1 2 20 9

Sample Output

YES
NO
NO

要求找到4个整数Np、Nq、Nr、Ns(1<= p < q < r < s <= k)s.t. Nq > Ns > Np > Nr or Nq < Ns < Np < Nr。

先看第一种情况,下标第二大的,值最大,而下标第三大的,值最小,下标最小和最大的都插在了中间,确定这个要求后,先想到dfs求解,但是考虑到5000这个数量比较大,怕函数进出栈太慢。

直接枚举四个值时间复杂度又太高了,所以只枚举两个,枚举Ns和Np,然后记录找到Nq和Nr。

用了两个标记数组, l[i][j] 表示下标小于j且值比Ni大的数中最小值的位置,r[i][j] 表示下标大于j且值比Ni小的数中最大值的位置。

最后在枚举判断就完成了第一种情况。第二种情况直接把数组翻转,然后在判断一次就行了。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <cmath>
#include <functional>

using namespace std;

const int maxn = 5005;
int num[maxn], l[maxn][maxn], r[maxn][maxn];
// l[i][j]表示下标小于j且值比Ni大的数中最小值的位置
// r[i][j]表示下标大于j且值比Ni小的数中最大值的位置
int k;

bool solve()
{
	for (int i = 1; i <= k; i++) {
		l[i][0] = 0;
		for (int j = 1; j < i; j++) { // 枚举Nq和Nr,找Np
			if (num[i] >= num[j]) {
				l[i][j] = l[i][j - 1];
			}
			else if (!l[i][j - 1] || num[j] < num[l[i][j - 1]]) {
				l[i][j] = j;
			}
			else {
				l[i][j] = l[i][j - 1];
			}
		}

	}

	for (int i = 1; i <= k; i++) {
		r[i][k + 1] = 0;
		for (int j = k; j > i; j--) {// 枚举Nq和Nr,找Ns
			if (num[i] <= num[j]) {
				r[i][j] = r[i][j + 1];
			}
			else if (!r[i][j + 1] || num[j] > num[r[i][j + 1]]) {
				r[i][j] = j;
			}
			else {
				r[i][j] = r[i][j + 1];
			}
		}
	}

	//i是q,j是r
	for (int i = 1; i <= k; i++) {
		for (int j = i + 1; j <= k; j++) {
			if (!l[j][i - 1] || !r[i][j + 1] || num[i] <= num[j]) {
				continue;
			}
			int p = l[j][i - 1], s = r[i][j + 1];
			if (num[j] < num[p] && num[p] < num[s] && num[s] < num[i]) {
				return true;
			}
		}
	}
	return false;
}

int main()
{
	ios::sync_with_stdio(false);
	int T;
	cin >> T;
	while (T--) {
		cin >> k;
		for (int i = 1; i <= k; i++) {
			cin >> num[i];
		}

		if (solve()) {
			cout << "YES\n";
		}
		else {
			reverse(num + 1, num + k + 1);
			if (solve()) {
				cout << "YES\n";
			}
			else {
				cout << "NO\n";
			}
		}
	}

	return 0;
}

UVa - 1618 - Weak Key的更多相关文章

  1. UVA - 1618 Weak Key(RMQ算法)

    题目: 给出k个互不相同的证书组成的序列Ni,判断是否存在4个证书Np.Nq.Nr.Ns(1≤p<q<r<s≤k)使得Nq>Ns>Np>Nr或者Nq<Ns&l ...

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

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举N[q]和N[r]的位置 因为N[q]是最大值,且N[r]是最小值. 且它们是中间的两个. 枚举这两个可以做到不重复枚举. 然后 ...

  3. 弱键(Weak Key, ACM/ICPC Seoul 2004, UVa1618)

    I think: 给出k(4≤k≤5000)个互不相同的整数组成的序列Ni,判断是否存在4个整数Np.Nq.Nr和Ns(1≤p<q<r<s≤k),使得Nq>Ns>Np&g ...

  4. 紫书 习题 8-16 UVa 1618 (中途相遇法)

    暴力n的四次方, 然而可以用中途相遇法的思想, 分左边两个数和右边两个数来判断, 最后合起来判断. 一边是n平方logn, 合起来是n平方logn(枚举n平方, 二分logn) (1)两种比较方式是相 ...

  5. UVA1618-Weak Key(RMQ)

    Problem UVA1618-Weak Key Accept: 103  Submit: 588Time Limit: 3000 mSec Problem Description Cheolsoo ...

  6. 多线程爬坑之路-Thread和Runable源码解析

    多线程:(百度百科借一波定义) 多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提 ...

  7. java中Map,List与Set的区别(转)

    Set,List,Map的区别 java集合的主要分为三种类型: Set(集) List(列表) Map(映射) 要深入理解集合首先要了解下我们熟悉的数组: 数组是大小固定的,并且同一个数组只能存放类 ...

  8. 浅谈Java中的Set、List、Map的区别(转)

    对JAVA的集合的理解是想对于数组: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),JAVA集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java ...

  9. des (C语言)

    /** * \file des.h * * \brief DES block cipher * * Copyright (C) 2006-2010, Brainspark B.V. * * This ...

随机推荐

  1. C++笔记003:从一个小程序开始

      原创笔记,转载请注明出处! 点击[关注],关注也是一种美德~ 安装好VS2010后,从第一个小程序开始. 在学习C语言时,我首先输出了一个程序员非常熟悉的对这个世界的问候:hello world! ...

  2. 全网代理公开ip爬取(隐藏元素混淆+端口加密)

    简述 本次要爬取的网站是全网代理,貌似还是代理ip类网站中比较有名的几个之一,其官网地址: http://www.goubanjia.com/. 对于这个网站的爬取是属于比较悲剧的,因为很久之前就写好 ...

  3. JavaScript Window History

    window.history 对象包含浏览器的历史. Window History window.history对象在编写时可不使用 window 这个前缀. 为了保护用户隐私,对 JavaScrip ...

  4. Bootstrap3 栅格系统-实例:多余的列(column)将另起一行排列

    如果在一个 .row 内包含的列(column)大于12个,包含多余列(column)的元素将作为一个整体单元被另起一行排列. <div class="row"> &l ...

  5. 用Python最原始的函数模拟eval函数的浮点数运算功能

    前几天看一个网友提问,如何计算'1+1'这种字符串的值,不能用eval函数. 我仿佛记得以前新手时,对这个问题完全不知道如何下手. 我觉得处理括号实在是太复杂了,多层嵌套括号怎么解析呢?一些多余的括号 ...

  6. OpenCV, MatBGR2ARGB, ARGB2MatBGR

    代码片段~ unsigned int* abMatBGR2ARGB(Mat imag) { int nCols; int nRows; unsigned int *pbuff = NULL; if(i ...

  7. 15 ActionBar.Tab 以及保存fragment对象 代码案例

    API 21弃用 values 中 string文件源码: <?xml version="1.0" encoding="utf-8"?> <r ...

  8. iOS下JS与原生OC互相调用(总结)

    这是去年总结的一篇文章,也一并先放到这个目录下好了. iOS开发免不了要与UIWebView打交道,然后就要涉及到JS与原生OC交互,今天总结一下JS与原生OC交互的两种方式. JS调用原生OC篇 方 ...

  9. Java程序员的必备知识-类加载机制详解

    类加载器的概念 类加载器是一个用来加载类文件的类. Java源代码通过javac编译器编译成类文件.然后JVM来执行类文件中的字节码来执行程序.类加载器负责加载文件系统.网络或其他来源的类文件. JV ...

  10. Tomcat集群应用部署的实现机制

    集群应用部署是一个很重要的应用场景,设想一下如果没有集群应用部署功能,每当我们发布应用时都要登陆每台机器对每个tomcat实例进行部署,这些工作量都是繁杂且重复的,而对于进步青年的程序员来说是不能容忍 ...