BZOJ 3207: 花神的嘲讽计划Ⅰ|莫队|主席树|hash

来源:互联网 发布:巫师2低配置优化补丁 编辑:程序博客网 时间:2024/05/08 07:26

本来以为会卡主席树内存,然后写了莫队T到死,发现想多了……
然而这题并不卡内存,直接主席树做就好了。
先给长度为K的序列hash一下然后就变成了询问一个区间内有没有某一个数,我离散化了一下,然后改成主席树发现又T到死……woc…终于发现二分查找有鬼..
然后就发现似乎莫队和主席树的二分都是一样的都有鬼..改了一下发现都能过,而且,而且莫队比主席树要快!!!!!!!!!!
发现主席树似乎并不需要离线离散化,只要强行扩大保存的区间的范围就好,因为复杂度是log的所以强行扩大范围的话复杂度多不了多少
code,主席树

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<set>#include<map>#include<iostream>#include<algorithm>#define ll unsigned long long#define N 500022using namespace std;int sc(){    int i=0,f=1; char c=getchar();    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();    return i*f;}struct W{int l,r,pos;ll v;}A[N];struct U{int pos;ll v;}h[N];ll hash[N],a[N],bin[N];int sum[N],v[N],ans[N],root[N];int n,m,k,tot,cnt;int ch[5001000][2],sm[5001000];bool cmp(U a,U b){    return a.v<b.v;}   void add(int pre,int &x,int l,int r,int v){    if(!x)x=++cnt;    sm[x]=sm[pre]+1;    if(l==r)return;    int mid=l+r>>1;    if(v>mid)        ch[x][0]=ch[pre][0],        add(ch[pre][1],ch[x][1],mid+1,r,v);    else        ch[x][1]=ch[pre][1],        add(ch[pre][0],ch[x][0],l,mid,v);}int ask(int L,int R,int v){    int l=1,r=tot;    while(l!=r)    {        int mid=l+r>>1,e=(v>mid);        e?l=mid+1:r=mid;        L=ch[L][e],R=ch[R][e];        if(sm[R]-sm[L]==0)return 0;    }    return sm[R]-sm[L];}int main(){    n=sc(),m=sc(),k=sc();bin[0]=1;    for(int i=1;i<=n;i++)    {        a[i]=a[i-1]*233+sc();        bin[i]=bin[i-1]*233;    }    for(int i=k;i<=n;i++)        h[i-k+1].v=a[i]-a[i-k]*bin[k],        h[i-k+1].pos=i-k+1;    n=n-k+1;    sort(h+1,h+n+1,cmp);    for(int i=1;i<=n;i++)        v[h[i].pos]=(h[i].v==h[i-1].v?tot:++tot),        hash[tot]=h[i].v;    for(int i=1;i<=n;i++)        add(root[i-1],root[i],1,tot,v[i]);    for(int i=1;i<=m;i++)    {        A[i].l=sc();        A[i].r=sc()-k+1;        for(int j=1;j<=k;j++)A[i].v=A[i].v*233+sc();        int x=lower_bound(hash+1,hash+tot+1,A[i].v)-hash;        if(hash[x]!=A[i].v||A[i].r<A[i].l)puts("Yes");        else        {            if(ask(root[A[i].l-1],root[A[i].r],x)) puts("No");            else puts("Yes");        }    }    return 0;}

code,莫队

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<set>#include<map>#include<iostream>#include<algorithm>#define ll unsigned long long#define N 500022using namespace std;int sc(){    int i=0,f=1; char c=getchar();    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();    return i*f;}struct W{int l,r,pos;ll v;}A[N];struct U{int pos;ll v;}h[N];ll hash[N],a[N],bin[N];int sum[N],bl[N],v[N],ans[N];int n,m,k,block,tot;bool cmp(U a,U b){    return a.v<b.v;}bool cmp1(W a,W b){    return bl[a.l]==bl[b.l]?a.r<b.r:bl[a.l]<bl[b.l];}int find(ll x){    int l=1,r=tot;    while(l<r)    {        int mid=l+r>>1;        if(hash[mid]==x)return mid;        else if(hash[mid]<x) l=mid+1;        else r=mid-1;    }    return hash[l]==x?l:0;}       int main(){    n=sc(),m=sc(),k=sc();block=sqrt(n);bin[0]=1;    for(int i=1;i<=n;i++)    {        bl[i]=(i-1)/block+1;        a[i]=a[i-1]*233+sc();        bin[i]=bin[i-1]*233;    }    for(int i=k;i<=n;i++)        h[i-k+1].v=a[i]-a[i-k]*bin[k],        h[i-k+1].pos=i-k+1;    n=n-k+1;    sort(h+1,h+n+1,cmp);    for(int i=1;i<=n;i++)        v[h[i].pos]=(h[i].v==h[i-1].v?tot:++tot),        hash[tot]=h[i].v;    for(int i=1;i<=m;i++)    {        A[i].l=sc();        A[i].r=sc()-k+1;        A[i].pos=i;        for(int j=1;j<=k;j++)A[i].v=A[i].v*233+sc();    }    sort(A+1,A+m+1,cmp1);    int l=1,r=0;    for(int i=1;i<=m;i++)    {        int x=find(A[i].v);        if(!x||A[i].r<A[i].l)continue;        while(l<A[i].l)sum[v[l++]]--;        while(l>A[i].l)sum[v[--l]]++;        while(r>A[i].r)sum[v[r--]]--;        while(r<A[i].r)sum[v[++r]]++;        if(sum[x])ans[A[i].pos]=1;    }    for(int i=1;i<=m;i++)ans[i]?puts("No"):puts("Yes");    return 0;}
0 0
原创粉丝点击