因为K是固定的,我们把原串的所有长度为K的子串都hash了。
每次查询就相当于在区间内询问一个数是否存在。可以主席树来搞一搞,也可以离线莫队什么的。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ull unsigned long long
#define inf 18446744073709551615ull
#define N 200010
#define k1 10016959
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,m,K,owo=0,rt[N];
ull hs[N],hsK=1;//hs[i]--1...i
struct node{
int lc,rc,sum;
}tr[N*50];
inline void add(int &p,ull l,ull r,ull x){
tr[++owo]=tr[p];p=owo;tr[p].sum++;
if(l==r) return;ull mid=(l>>1)+(r>>1)+(l&r&1);
if(x<=mid) add(tr[p].lc,l,mid,x);
else add(tr[p].rc,mid+1,r,x);
}
inline bool ask(int p1,int p2,ull l,ull r,ull x){
if(tr[p1].sum-tr[p2].sum==0) return 0;
if(l==r) return 1;ull mid=(l>>1)+(r>>1)+(l&r&1);
if(x<=mid) return ask(tr[p1].lc,tr[p2].lc,l,mid,x);
return ask(tr[p1].rc,tr[p2].rc,mid+1,r,x);
}
int main(){
// freopen("a.in","r",stdin);
n=read();m=read();K=read();
for(int i=1;i<=n;++i){
int x=read();
hs[i]=hs[i-1]*k1+x;
}for(int i=1;i<=K;++i) hsK*=k1;
for(int i=K;i<=n;++i){
rt[i]=rt[i-1];add(rt[i],0ull,inf,hs[i]-hs[i-K]*hsK);
}while(m--){
int x=read(),y=read();ull res=0;
for(int i=1;i<=K;++i) res=res*k1+read();
if(ask(rt[y],rt[x+K-2],0ull,inf,res)) puts("No");
else puts("Yes");
}return 0;
}