hdu 5172 GTY's gay friends (线段树||hash)

来源:互联网 发布:淘宝友臣肉松饼是假的 编辑:程序博客网 时间:2024/04/26 12:53

题意:

n个数m个询问,询问(l,r)中的数是否为1 ~ r-l+1的一个排列。

分析:

若(l,r)中的数为1 ~ r-l+1中的一个排列,则必须满足:

1、(l,r)中的数之和为len*(len+1)/2,其中len = r-l+1。

2、区间内的数字各不相同,即用线段树维护位置i上的数上次出现的位置的最大值。

只要区间内所有的数上次出现的位置last[i] < l,则区间内的数各不相同。


#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<cmath>#include<vector>#include<queue>#include<map>using namespace std;typedef long long ll;const int maxn = 1000010;ll sum[maxn];int tre[maxn<<2];int last[maxn],pos[maxn];void PushUp(int rt){    tre[rt] = max(tre[rt<<1],tre[rt<<1|1]);}void build(int rt,int l,int r){    if(l==r)    {        tre[rt] = last[l];        return;    }    int mid = (l+r)>>1;    build(rt<<1,l,mid);    build(rt<<1|1,mid+1,r);    PushUp(rt);}ll query(int rt,int l,int r,int q1,int q2){    if(q1<=l && r<=q2) return tre[rt];    int mid = (l+r)>>1;    ll ret = 0;    if(q1<=mid) ret = max(ret,query(rt<<1,l,mid,q1,q2));    if(q2>mid) ret = max(ret,query(rt<<1|1,mid+1,r,q1,q2));    return ret;}int main(){    int n,m,x;    while(~scanf("%d%d",&n,&m))    {        memset(sum,0,sizeof(sum));        memset(pos,0,sizeof(pos));        for(int i=1;i<=n;i++)        {            scanf("%d",&x);            sum[i] = sum[i-1]+x;            last[i] = pos[x];            pos[x] = i;        }        build(1,1,n);        ll l,r;        while(m--){            scanf("%I64d%I64d",&l,&r);            ll len = r-l+1;            if((sum[r]-sum[l-1]==len*(len+1)/2) && query(1,1,n,l,r)<l) puts("YES");            else puts("NO");        }    }    return 0;}


hash做法:

对于[1-n]中的每一个数随机一个64位无符号整型作为它的hash值,一个集合的hash值为元素的异或和,预处理[1-n]的排列的hash和原序列的前缀hash异或和,就可以做到线性预处理,O(1)回答询问.
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<cmath>#include<vector>#include<queue>#include<map>#include<ctime>#define eps (1e-8)using namespace std;typedef long long ll;unsigned long long ra[1000005],a[1000005],ha[1000005];int n,m,t,p;//int main(int argc,char const *argv[])int main(){    srand(time(NULL));    a[0] = ha[0] = 0;    for(int i=1;i<=1000000;i++){        ra[i] = rand()*rand();        ha[i] = ha[i-1]^ra[i];    }    while(~scanf("%d%d",&n,&m))    {        for(int i=1;i<=n;i++){            scanf("%d",&t);            a[i] = ra[t];            a[i]^=a[i-1];        }        for(int i=1;i<=m;i++){            scanf("%d%d",&t,&p);            puts((ha[p-t+1]==(a[p]^a[t-1])?"YES":"NO"));        }    }    return 0;}



0 0
原创粉丝点击