HDU5172GTY's gay friends——区间查询(区间内的数互不相同)

http://acm.split.hdu.edu.cn/showproblem.php?pid=5172

官方题解
一个区间是排列只需要区间和为len(len+1)2(len为区间长度),且互不相同,对于第一个问题我们用前缀和解决,对于第二个问题,预处理每个数的上次出现位置,记它为pre,互不相同即区间中pre的最大值小于左端点,使用线段树或Sparse Table即可在O(n)/O(nlogn)的预处理后 O(logn)/O(1)回答每个询问.不过我们还有更简单的hash做法,对于[1..n]中的每一个数随机一个64位无符号整型作为它的hash值,一个集合的hash值为元素的异或和,预处理[1..n]的排列的hash和原序列的前缀hash异或和,就可以做到线性预处理,O(1)回答询问.

前缀和+线段树
1419MS 25360K 1368 B

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=1100000;
using namespace std;
int n,m;
ll c[maxn];
int head[maxn],pre[maxn];
void addnode(int p,int x){
    pre[p]=head[x];
    head[x]=p;
}

int mx[maxn<<2];
void push_up(int rt){
    mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void build(int l,int r,int rt){
    if(l==r){
        mx[rt]=pre[l];
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(rt);
}
int query(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R){
        return mx[rt];
    }
    int m=(l+r)>>1;
    int vmax=-1;
    if(L<=m) vmax=max(vmax,query(L,R,lson));
    if(m<R) vmax=max(vmax,query(L,R,rson));
    return vmax;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF){
        c[0]=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n;++i){
            scanf("%I64d",&c[i]);
            addnode(i,c[i]);
            c[i]+=c[i-1];
        }
        build(1,n,1);
        int l,r;
        while(m--){
            scanf("%d%d",&l,&r);
            ll ans=c[r]-c[l-1];
            ll len=r-l+1;
            if(ans==len*(len+1)/2&&query(l,r,1,n,1)<l) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值