您的位置:首页 > 其它

BZOJ 3207 花神的嘲讽计划Ⅰ主席树+Hash

2015-09-29 17:21 411 查看
题意:

当前有一个序列。

多次询问某一个子序列中是否存在某一个长度为k的序列(连续)。

非强制在线。

解析:

由于本题非强制在线所以可能有各种奇怪的方法叉过去。

但是咱们要把它看成强制在线的来做嘛!

由于题中这个K的限制非常好。

所以我们可以预处理出所有的点到其+k-1的子区间的hash值。

然后扔到权值线段树中。

但是这里有个问题就是我们一个线段树的话版本不够?

我们需要查询某一段区间中是否存在一个询问的Hash。

所以这里可以考虑上一个主席树。

即可解决。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100100
#define base 131
#define INF 18446744073709551615ull
using namespace std;
typedef unsigned long long ull;
int n,m,k;
int size;
int a
;
int root
;
struct node
{
int lson,rson,sum;
}seg[N*70];
void insert(int x,int &y,ull l,ull r,ull v)
{
y=++size;
seg[y]=seg[x];
seg[y].sum++;
if(l==r)return;
ull mid=(l>>1)+(r>>1)+(l&r&1);
if(v<=mid)insert(seg[x].lson,seg[y].lson,l,mid,v);
else insert(seg[x].rson,seg[y].rson,mid+1,r,v);
}
int query(int x,int y,ull l,ull r,ull v)
{
if(seg[y].sum-seg[x].sum==0)return 0;
if(l==r)return 1;
ull mid=(l>>1)+(r>>1)+(l&r&1);
if(v<=mid)return query(seg[x].lson,seg[y].lson,l,mid,v);
else return query(seg[x].rson,seg[y].rson,mid+1,r,v);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
ull hash=0;
for(int j=i;j<=i+k-1;j++)
{
hash=hash*base+a[j];
}
insert(root[i-1],root[i],0,INF,hash);
}
for(int i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
ull hash=0;
for(int j=1;j<=k;j++)
{
int v;
scanf("%d",&v);
hash=hash*base+v;
}
if(query(root[l-1],root[r-k+1],0,INF,hash))puts("No");
else puts("Yes");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: