Hdu 5172 GTY's gay friends

来源:互联网 发布:堆排序算法实现 编辑:程序博客网 时间:2024/04/25 16:50

题目链接:点击打开链接

题目大意就是,给一段序列,长度为10^5,然后有10^5个询问,每次询问为一个区间,l为左边界,r为右边界,该区间是否为一个1到r-l+1的一个排列,即该区间是否满足包含1到r-l+1的所有元素。

分析一下,如果一个长度为n的区间包含从1到n的所有元素,那么在该区间之内,1到n的元素每个只出现一次,而且这个区间和应该为n(n+1)/2。第二个条件只需要处理前缀和即可,第一个条件则需要查重。

第一个我用的是线段树,每一个位置记录一下当前元素出现的上一个位置在哪里,然后以记录为元素建线段树,线段树的每个节点保存当前区间里重复出现的最后一个位置,对于查询只需要看重复位置是否出现在区间之内。

貌似出题人还提出一种哈希查重的方法,给1到n个元素随机一个哈希值,用集合元素的异或和作为哈希值,预处理出前n个元素的哈希值,然后o(1)查重...个人感觉存在满足哈希值相同且和相同的两个集合...用以自身为哈希值的方法交了一发,在一个大数据前面wa了,应该是个不稳定的方法...

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;#define N 1000010#define ls rt << 1#define rs rt << 1 | 1#define LL long longstruct node{    int l,r;    int pre;}T[N<<2];LL sum[N];int pre[N],now[N];void Pushup(int rt){     T[rt].pre = max(T[ls].pre , T[rs].pre);}void build(int l,int r,int rt){     T[rt].l = l;     T[rt].r = r;     if(l == r){        T[rt].pre = now[l];        return ;     }     int m = (l + r) >> 1;     build(l,m,ls);     build(m + 1,r,rs);     Pushup(rt);}LL SUM(int l,int r){    LL a = r - l + 1,ret;    ret = ((LL)1+a)*a/(LL)2;    return ret;}int query(int l,int r,int rt){     if(l <= T[rt].l && T[rt].r <= r){        return T[rt].pre;     }     int ret = -1;     if( l <= T[ls].r ) ret = query(l,r,ls);     if( r >= T[rs].l) ret = max(ret, query(l,r,rs));     return ret;}int main(){    int n,m,t,l,r;    LL ans;    sum[0] = 0;    while(~scanf("%d%d",&n,&m)){        memset(pre,-1,sizeof(pre));        for(int i=1;i<=n;i++){            scanf("%d",&t);            if(i==1){                sum[i] = t;            }            else sum[i] = sum[i - 1] + (LL)t;           // printf("%I64d ",sum[i]);//shan            if(pre[t] == -1){                now[i] = -1;                pre[t] = i;            }            else{                now[i] = pre[t];                pre[t] = i;            }        }        //printf("\n");// shan        build(1,n,1);        //printf("1\n");        for(int i=0;i<m;i++){            scanf("%d%d",&l,&r);            ans = sum[r] - sum[l - 1];            if(ans == SUM(l,r)){            ans = query(l,r,1);            if(ans >= l){                printf("NO\n");            }            else {                printf("YES\n");            }            }            else{                printf("NO\n");            }        }    }    return 0;}


0 0
原创粉丝点击