BZOJ 3207フローラ嘲笑計画I(ハッシュ)

問題の意味

アレイ1E5、1E5問い合わせ、グループ番号、および(L、R)のあなたの(<= 20)の長さとそれぞれ同一では、あなたが求めることがグループの数は、サブストリング(L、R)内にありません

思考

私はアイデアが...だけで結構だと思い
ハッシュ(私、私は+ K-1アウト ) ツリー内の各照会の後、会長、ストリングの、データの彼自身のセットを構築するの多くはスローされませんでしたされている..しかし、なぜWA分かりません...エラーが(エラーがハッシュ係数愚かである)
前に見たオンラインSTL、自身が広がった
だけで、ハッシュのセット内の各文字列を尋ねるために、でスロー同じハッシュ値のセットの最初の列プレゼンスと<= R-K + 1缶を決定LOWER_BOUND(L)、中

合計すると思われる:ライン上半分に設定した範囲内の値があるかどうかを判断するために?

コード

半分に範囲:

int t;
int n,m,k;
ll a[maxn];
ull pre[maxn];
ull po[maxn];
ll gt(int l, int r){
    return (pre[r]-pre[l-1]*po[r-l+1]);
}
vector<ll>v;
int getid(ll x){
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
set<int>s[maxn];
int main() {
    po[0]=1;
    scanf("%d %d %d", &n, &m, &k);
    for(int i = 1; i <= n; i++)po[i]=po[i-1]*1337;
    for(int i = 1; i <= n; i++){
        scanf("%lld", &a[i]);
        pre[i]=pre[i-1]*1337+a[i];
    }
    for(int i = 1; i+k-1<=n; i++){
        v.pb(gt(i,i+k-1));
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    int ntot = v.size();
    for(int i = 1; i+k-1<=n; i++){
        a[i]=getid(gt(i,i+k-1));
        s[a[i]].insert(i);
    }
    while(m--){
        int x,y;
        ll tmp = 0;
        scanf("%d %d", &x, &y);
        for(int i = 1; i <= k; i++){
            int o;
            scanf("%d", &o);
            tmp=tmp*1337+o;
        }
        int id = getid(tmp);
        if(v[id-1]!=tmp){
            printf("Yes\n");
            continue;
        }
        set<int>::iterator it = s[id].lower_bound(x);
        if(it!=s[id].end()&&*it<=y-k+1)printf("No\n");
        else printf("Yes\n");

    }

    return 0;
}

木の会長:

int t;
int n,m,k;
ll a[maxn];
ull pre[maxn];
ull po[maxn];
ull gt(int l, int r){
    return (pre[r]-pre[l-1]*po[r-l+1]);
}
vector<ull>v;
int getid(ull x){
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
int ls[40*maxn],rs[40*maxn];
ll dat[40*maxn];
int root[maxn];
int tot;
int insert(int now, int l, int r, int x, int val){
    int p = ++tot;
    ls[p]=ls[now];rs[p]=rs[now];dat[p]=dat[now];
    if(l==r){
        dat[p]=1;return p;
    }
    int mid = l+r>>1;
    if(x<=mid)ls[p]=insert(ls[now],l,mid,x,val);
    else rs[p]=insert(rs[now],mid+1,r,x,val);
    dat[p]=dat[ls[p]]+dat[rs[p]];
    return p;
}
int ck(int x, int y, int l, int r, int k){
    int mid =l+r>>1;
    if(l==r)return dat[y]-dat[x];
    if(k<=mid){
        return ck(ls[x],ls[y],l,mid,k);
    }
    else return ck(rs[x],rs[y],mid+1,r,k);

}

int main() {
    //freopen("wrjAc.in","r",stdin);
    //freopen("wrjMy.out","w",stdout);
    scanf("%d %d %d", &n, &m, &k);
    po[0]=1;
    for(int i = 1; i <= n; i++)po[i]=po[i-1]*1337;
    for(int i = 1; i <= n; i++){
        scanf("%lld", &a[i]);
        pre[i]=pre[i-1]*1337+a[i];
    }
    for(int i = 1; i+k-1<=n; i++){
        v.pb(gt(i,i+k-1));
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    int ntot = v.size();
    for(int i = 1; i+k-1<=n; i++){
        a[i]=getid(gt(i,i+k-1));
        root[i]=insert(root[i-1],1,ntot,a[i],1);
    }
    while(m--){
        int x,y;
        ull tmp = 0;
        scanf("%d %d", &x, &y);
        for(int i = 1; i <= k; i++){
            int o;
            scanf("%d", &o);
            tmp=tmp*1337+o;
        }
        int id = getid(tmp);
        if(v[id-1]!=tmp){
            printf("Yes\n");
            continue;
        }

        int ans = ck(root[x-1],root[y-k+1],1,ntot,id);
        if(ans>0)printf("No\n");
        else printf("Yes\n");

    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/wrjlinkkkkkk/p/12596096.html