[BZOJ3207]花神的嘲讽计划

hash+主席树,把hash值挂到主席树上,查询区间是否存在即可。
(我才不会告诉你我的模数被卡了5发)

#include <iostream>
#include <cstdio>
#include <cstring>
typedef unsigned long long ll;
using namespace std;
int n,m,k,rt[200005],ls[100010*90],rs[200005*45],tot,siz[200005*45];long long a[200005];
const ll mod=998244353LL*157+1;
void update(int &k,int pre,ll l,ll r,ll c) {
    ls[k=++tot]=ls[pre],rs[k]=rs[pre],siz[k]=siz[pre]+1;
    if(l==r)return;
    ll mid=l+r>>1;
    if(c<=mid) update(ls[k],ls[pre],l,mid,c);
    else update(rs[k],rs[pre],mid+1,r,c);
}
int query(int u,int v,ll l,ll r,ll c) {
    if(!v) return 0;
    if(l==r) {
        if(siz[v]-siz[u]>0) return 1;
        return 0;
    }
    ll mid=l+r>>1;
    if(mid<c) return query(rs[u],rs[v],mid+1,r,c);
    return query(ls[u],ls[v],l,mid,c);
}
int main() {
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
    for(int i=1; i<=n-k+1; i++) {
        ll res=0;
        for(int j=0; j<k; j++) res=(res*17ll+a[i+j])%(mod);
        update(rt[i],rt[i-1],0,mod,res);
    }
    for(int i=1,x,y; i<=m; i++) {
        ll res=0;
        scanf("%d%d",&x,&y);
        y-=k-1;
        for(ll j=1,tp; j<=k; j++) scanf("%lld",&tp),res=(res*17ll+tp)%(mod);
        if(x<=y&&query(rt[x-1],rt[y],0,mod,res)) puts("No");
        else puts("Yes");
    }
}

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9485259.html