hdu5172 GTY‘s gay friends(hash判断排列)

题意:

给定长度为n的序列a,m个询问
每个询问:
问区间[l,r]中的数是否是1-(r-l+1)的一个排列(全排列中的一种)

数据范围:n<=1e6,1<=a(i)<=n

解法:

n最大1e6,给1到1e6的每个数随机一个hash值,预处理异或前缀和h_pre[]
然后用前面的hash数组对给定的序列a计算异或前缀和,a_pre[]
如果a_pre[r]^a_pre[l-1]==h_pre[r-l+1],那么说明是排列。

正确性显然,因为[l,r]的异或和等于1到n的异或和,那么肯定是排列。

code:
#include <bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int maxm=1e6+5;
ull h[maxm];
ull h_pre[maxm];//前缀异或和
int a[maxm];
ull a_pre[maxm];
int n,m;
signed main(){
    for(int i=1;i<maxm;i++){
        h[i]=rand()*rand();
        h_pre[i]=h_pre[i-1]^h[i];
    }
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            a_pre[i]=a_pre[i-1]^h[a[i]];
        }
        while(m--){
            int l,r;scanf("%d%d",&l,&r);
            if(h_pre[r-l+1]==(a_pre[r]^a_pre[l-1])){
                puts("YES");
            }else{
                puts("NO");
            }
        }
    }
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值