题目大意:给出一个序列,问一个区间里有没有长度为定长的已知序列。
思路:第一步的想法是把序列哈希一下,如果暴力的话,就是在区间里面O(n)的去判断,但是这样显然太慢了,我们需要O(logn)的时间之内求出区间内有没有一个值。这个问题就可以用可持久化线段树或者划分树来解决了。划分树我不咋会,就写了可持久化线段树。代码略丑,见谅。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 200010
#define MAX_POOL (MAX * 50)
#define MAX_ULL 18446744073709551615ull
using namespace std;
const int key = 999911659;
const int _key = 999911657;
struct SegTree{
int cnt;
SegTree *son[2];
}*tree[MAX],mempool[MAX_POOL],*C = mempool;
int cnt,asks,length;
int src[MAX];
unsigned long long _hash[MAX],hash[MAX];
unsigned long long power[MAX];
void Pretreatment()
{
power[0] = 1;
for(int i = 1; i <= length; ++i)
power[i] = power[i - 1] * key;
}
inline SegTree *NewNode(int _,SegTree *__,SegTree *___)
{
C->cnt = _;
C->son[0] = __;
C->son[1] = ___;
return C++;
}
SegTree *BuildTree(SegTree *consult,unsigned long long l,unsigned long long r,unsigned long long x)
{
if(l == r) return NewNode(consult->cnt + 1,NULL,NULL);
unsigned long long mid = (l >> 1) + (r >> 1) + (l&r&1);
if(x <= mid) return NewNode(consult->cnt + 1,BuildTree(consult->son[0],l,mid,x),consult->son[1]);
else return NewNode(consult->cnt + 1,consult->son[0],BuildTree(consult->son[1],mid + 1,r,x));
}
bool Ask(SegTree *end,SegTree *start,unsigned long long l,unsigned long long r,unsigned long long x)
{
if(!(end->cnt - start->cnt)) return false;
if(l == r) return true;
unsigned long long mid = (l >> 1) + (r >> 1) + (l&r&1);
if(x <= mid) return Ask(end->son[0],start->son[0],l,mid,x);
return Ask(end->son[1],start->son[1],mid + 1,r,x);
}
int main()
{
cin >> cnt >> asks >> length;
Pretreatment();
for(int i = 1; i <= cnt; ++i) {
scanf("%d",&src[i]);
_hash[i] = _hash[i - 1] * key + src[i];
}
tree[length - 1] = NewNode(0,C,C);
for(int i = length; i <= cnt; ++i) {
hash[i] = _hash[i] - _hash[i - length] * power[length];
tree[i] = BuildTree(tree[i - 1],0,MAX_ULL,hash[i]);
}
for(int x,y,i = 1; i <= asks; ++i) {
scanf("%d%d",&x,&y);
unsigned long long hash = 0;
for(int z,j = 1; j <= length; ++j) {
scanf("%d",&z);
hash = hash * key + z;
}
x = x + length - 1;
if(x > y) printf("Yes\n");
else printf("%s\n",Ask(tree[y],tree[x - 1],0,MAX_ULL,hash) ? "No":"Yes");
}
return 0;
}