HDU 5172 GTY's gay friends

来源:互联网 发布:虚幻4与unity3d 编辑:程序博客网 时间:2024/04/26 20:38

Problem Description

给出 n 个 1 到 n 的数字 a1,a2,...,an。m 组询问,每次询问给出一对整数 l,r。问 al,al+1,...,ar 是否是 1 到 (r-l+1) 的一个排列。

Input

多组测试样例,每组先给出 n 和 m;其后是 n 个数;再其后是 m 行,每行是一对整数 l,r。

1n,m1000000

Output

每组询问回答 YES 或者 NO

Solve1: prefix sum & rmq

我们把一个序列是一个排列这个条件看做要同时满足一下两点:

  1. 这个序列的和是要询问的排列的和
  2. 这个序列中元素两两不同。

第一点容易解决,我们可以使用前缀和数组。

第二点解决也不难。只要先预处理出 prei 表示在 i 之前最后一个与 ai 相等的数的位置(如果没有与之相等的位置那么设这个数是 0)。每次只要询问 (l, r) 内的 pre 的最大值,如果最大值小于 l ,说明命题成立;反之不成立。

于是第二点其实是一个 rmq 问题,遗憾的是 sparse table 在这个题目的限制内存下是不能用的。可以考虑线段树。

https://code.csdn.net/snippets/1582922/master/hdu5172.cpp/raw

Solve2: hash

hash 是一种比较时髦的做法。在这里使用是很巧妙的。

对于 1 到 n 每个数 i 我们随机一个整数(尽量随机范围大一点),作为 i 的哈希值。

我们把一段序列的哈希值设置为这个序列的数的哈希值的亦或值。

设置这两个哈希之后,我们考虑一个序列是一个排列,则必然两者的哈希值一样;反之哈希值一样,这个序列就很可能是一个排列。

我们处理 pre_hshi=hsh(a1)hsh(a2)...hsh(ai) 。那么所求序列的哈希值就是 pre_hshrpre_hshl1 。这由亦或的性质是容易看出来的。然后判断这个数是否等于 hsh(1)hsh(2)...hsh(rl+1) ,就解决了这个问题。

这种方法显然实现更容易,而且复杂度也低。

https://code.csdn.net/snippets/1582908/master/hdu5172%281%29.cpp/raw

0 0
原创粉丝点击