[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");
	}
}
posted @ 2018-08-16 08:55  SWHsz  阅读(143)  评论(0编辑  收藏  举报