HDU 5172 GTY's gay friends

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值