HDU 5172 GTY's gay friends(HASH 随机算法)

来源:互联网 发布:盛势网络剧什么时候播 编辑:程序博客网 时间:2024/04/27 07:23

【题意】给出一个长度为n的数组(n<=100W).每个数都<=100W。然后m次询问,每次询问l..r区间内是否为1..r-l+1的一个排列

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

【AC 代码】

<span style="font-family:Arial;">//Hash 算法</span>#include <time.h>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn=1000010;#define uLL unsigned __int64uLL XOR[maxn],a[maxn],sum[maxn];inline uLL RANDuLL(){    uLL one=1;    uLL RAND=(rand()+rand())*(one<<47)+(rand()+rand())*(one<<31)+(rand()+rand())*(one<<15)+(rand()+rand());    return RAND;}int main(){    srand(time(NULL));    XOR[0]=0;    for(int i=1; i<maxn; i++){        a[i]=RANDuLL();        XOR[i]=XOR[i-1]^a[i];    }    int n,m;    while(scanf("%d%d",&n,&m)!=EOF)    {        sum[0]=0;        int x;        for(int i=1; i<=n; i++){            scanf("%d",&x);            sum[i]=a[x]^sum[i-1];        }        int l,r;        while(m--){            scanf("%d%d",&l,&r);            if(XOR[r-l+1]==(sum[r]^sum[l-1])){                puts("YES");            }else{                puts("NO");            }        }    }}

【线段树版本】
<span style="font-family:Arial;">//代码来自上决</span><pre name="code" class="cpp">#include<iostream>  #include<algorithm>  #include<stdio.h>  #include<string.h>  using namespace std;  typedef __int64 LL;  #define NN 1000010  struct node  {      int l,r;      int id;  }q[NN];  bool cmp(node t1,node t2)  {      return t1.r<t2.r;  }  int mx[NN*3];  LL sum[NN*3];  void push_up(int id)  {      sum[id]=sum[id<<1]+sum[id<<1|1];      mx[id]=max(mx[id<<1],mx[id<<1|1]);  }  int MAX;  LL SUM;  void build()  {      memset(mx,0,sizeof(mx));      memset(sum,0,sizeof(sum));  }  void update(int id,int L,int R,int pos,int val,int mxx)  {      if(L==R)      {          sum[id]=(LL)val;          mx[id]=mxx;          return ;      }      int mid=(L+R)>>1;;      if(pos<=mid)          update(id<<1,L,mid,pos,val,mxx);      else          update(id<<1|1,mid+1,R,pos,val,mxx);      push_up(id);  }  void query(int id,int L,int R,int l,int r)  {      if(l<=L&&R<=r)      {          MAX=max(MAX,mx[id]);          SUM+=sum[id];          return ;      }      int mid=(L+R)>>1;      if(l<=mid)          query(id<<1,L,mid,l,r);      if(mid<r)          query(id<<1|1,mid+1,R,l,r);  }  int a[NN],p[NN],pre[NN];  inline int getint()  {      int c;      while (c = getchar(), c<'0' || '9'<c);      int res = c - 48;      while (c = getchar(), '0' <= c&&c <= '9') res = (res << 3) + res + res + c - 48;      return res;  }  int main()  {      int n,m;      while(scanf("%d %d",&n,&m)!=EOF)      {          for(int i=1;i<=n;i++) a[i]=getint();          for(int i=1;i<=m;i++)          {              q[i].l=getint();              q[i].r=getint();              q[i].id=i;          }          sort(q+1,q+m+1,cmp);          build();          memset(p,0,sizeof(p));          memset(pre,0,sizeof(pre));          for(int i=1;i<=n;i++)          {              pre[i]=p[a[i]];              p[a[i]]=i;          }          int t=1;          memset(p,0,sizeof(p));          for(int i=1;i<=n;i++)          {              update(1,1,n,i,a[i],pre[i]);              while(i==q[t].r)              {                  SUM=0;                  MAX=0;                  LL tt=(LL)(q[t].r-q[t].l+1);                  //printf("%d %d  %d??\n",q[t].l,q[t].r,q[t].id);                  LL sum=tt*(tt+1)/2;                  query(1,1,n,q[t].l,q[t].r);                  //printf("%I64d %d   %I64d  %d\n",tmp.sum,tmp.mx ,sum,q[t].l);                  if(sum==SUM && MAX < q[t].l)                  {                      p[q[t].id]=1;                  }                  ++t;              }          }          for(int i=1;i<=m;i++)          {              if(p[i]==1)                  puts("YES");              else puts("NO");          }        }      return 0;  }  



0 0