【字符串哈希】【莫队算法】bzoj3207 花神的嘲讽计划Ⅰ

既然询问的长度是确定的,那么我们可以将所有长度为K的字串弄个哈希值出来,这样字串存在性=>哈希值存在性。

自然上溢哈希,base=107比较不错。

序列长度n=>n-K+1

询问区间[x,y]=>[x,y-K+1]

注意特判x是否>y-K+1

然后我们注意到没有修改,于是将哈希值离散化后,莫队大法好。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
int f,C;
inline void R(int &x){
    C=0;f=1;
    for(;C<‘0‘||C>‘9‘;C=getchar())if(C==‘-‘)f=-1;
    for(x=0;C>=‘0‘&&C<=‘9‘;C=getchar())(x*=10)+=(C-‘0‘);
    x*=f;
}
#define N 200001
#define seed 107
ull seedK=1;
int n,m,K,a[N<<1],c[N],en,en2,X;
int num[N],b[N<<1],sum=1;
bool anss[N];
struct Point{ull v;int p;}t[N<<1];
struct Ask{int l,r,x,p;}Q[N];
bool operator < (const Point &a,const Point &b){return a.v<b.v;}
bool operator < (const Ask &a,const Ask &b)
{return num[a.l]!=num[b.l] ? num[a.l]<num[b.l] : a.r<b.r;}
void Mo_Make_Block()
{
    int sum=1,sz=sqrt(n); if(!sz) sz=1;
    for(;sum*sz<n;++sum)
      {
        int r=sum*sz;
        for(int i=(sum-1)*sz+1;i<=r;++i) num[i]=sum;
      }
    for(int i=(sum-1)*sz+1;i<=n;++i) num[i]=sum;
}
int main()
{
	R(n); R(m); R(K);
	for(int i=1;i<=K;++i)
	  seedK=seedK*seed;
	for(int i=1;i<=n;++i) R(c[i]);
	ull hs=0;
	for(int i=1;i<=K;++i) hs=hs*seed+(ull)c[i];
	for(int i=K+1;i<=n;++i)
	  {
	  	t[++en].v=hs; t[en].p=en;
	  	hs=hs*seed+(ull)c[i];
        hs-=c[en]*seedK;
	  }
	t[++en].v=hs; t[en].p=en;
	int Record=en;
	for(int i=1;i<=m;++i)
	  {
	  	R(Q[i].l); R(Q[i].r);
	  	Q[i].p=i;
	  	Q[i].r=Q[i].r-K+1;
	  	hs=0;
	  	for(int j=1;j<=K;++j)
	  	  {
	  	  	R(X);
	  	  	hs=hs*seed+(ull)X;
	  	  }
	  	t[++en].v=hs; t[en].p=en;
	  }
	sort(t+1,t+en+1);
	a[t[1].p]=++en2;
    for(int i=2;i<=en;++i)
      {
        if(t[i].v!=t[i-1].v) ++en2;
        a[t[i].p]=en2;
      }
    en=Record;
    for(int i=1;i<=m;++i) Q[i].x=a[++en];
	Mo_Make_Block();
	sort(Q+1,Q+m+1);
    for(int i=Q[1].l;i<=Q[1].r;++i) ++b[a[i]];
    if(Q[1].l<=Q[1].r) anss[Q[1].p]=b[Q[1].x];
    else anss[Q[1].p]=0;
    for(int i=2;i<=m;++i)
      {
        if(Q[i].l<Q[i-1].l) for(int j=Q[i-1].l-1;j>=Q[i].l;--j) ++b[a[j]];
        else for(int j=Q[i-1].l;j<Q[i].l;++j) --b[a[j]];
        if(Q[i].r<Q[i-1].r) for(int j=Q[i-1].r;j>Q[i].r;--j) --b[a[j]];
        else for(int j=Q[i-1].r+1;j<=Q[i].r;++j) ++b[a[j]];
        if(Q[i].l<=Q[i].r) anss[Q[i].p]=b[Q[i].x];
        else anss[Q[i].p]=0;
      }
    for(int i=1;i<=m;++i) puts(anss[i]?"No":"Yes");
	return 0;
}
时间: 2024-10-27 05:36:08

【字符串哈希】【莫队算法】bzoj3207 花神的嘲讽计划Ⅰ的相关文章

【Luogu】P3709大爷的字符串题(莫队算法)

题目链接 语文题啊…… 看题解发现是让求区间中最多的数的个数,于是果断理解了一会题解……莫队套上完事. sum[i]表示i这个数出现的次数,cnt[i]表示出现i次的数有几个,然后乱搞搞……就好了 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cctype> #include<cmath> #define maxn 3

[BZOJ3207] 花神的嘲讽计划Ⅰ (主席树)

Description 背景 花神是神,一大癖好就是嘲讽大J,举例如下: “哎你傻不傻的![hqz:大笨J]” “这道题又被J屎过了!!” “J这程序怎么跑这么快!J要逆袭了!” …… 描述 这一天DJ在给吾等众蒟蒻讲题,花神在一边做题无聊,就跑到了一边跟吾等众蒟蒻一起听.以下是部分摘录: 1. “J你在讲什么!” “我在讲XXX!” “哎你傻不傻的!这么麻烦,直接XXX再XXX就好了!” “……” 2. “J你XXX讲过了没?” “……” “那个都不讲你就讲这个了?哎你傻不傻的!” “……”

BZOJ3207 花神的嘲讽计划Ⅰ

Description 背景 花神是神,一大癖好就是嘲讽大J,举例如下: “哎你傻不傻的![hqz:大笨J]” “这道题又被J屎过了!!” “J这程序怎么跑这么快!J要逆袭了!” …… 描述 这一天DJ在给吾等众蒟蒻讲题,花神在一边做题无聊,就跑到了一边跟吾等众蒟蒻一起听.以下是部分摘录: 1. “J你在讲什么!” “我在讲XXX!” “哎你傻不傻的!这么麻烦,直接XXX再XXX就好了!” “……” 2. “J你XXX讲过了没?” “……” “那个都不讲你就讲这个了?哎你傻不傻的!” “……”

[bzoj3207]花神的嘲讽计划Ⅰ[可持久化线段树,hash]

将每k个数字求一个哈希值,存入可持久化线段树,直接查询即可 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 9 using namespace std; 10 11 #define

bzoj3207: 花神的嘲讽计划Ⅰ hash+stl

显然hash,然后stl随便搞. #include<bits/stdc++.h> #define N 100005 using namespace std; typedef unsigned long long ull; map<ull,vector<int> >q; int n,m,k,s,t,v,a[N]; int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;

BZOJ3207 花神的嘲讽计划

hash值建主席树. 垃圾题面没有熟虑范围害我MLE——>RE. By:大奕哥 1 #include<bits/stdc++.h> 2 #define unll unsigned long long 3 #define inf 18446744073709551615UL 4 using namespace std; 5 const int N=1000005; 6 struct node{ 7 int l,r,s; 8 }t[2000005]; 9 int a[N],rt[N],n,m

【bzoj3207】花神的嘲讽计划Ⅰ Hash+STL-map+莫队算法

题目描述 背景 花神是神,一大癖好就是嘲讽大J,举例如下: “哎你傻不傻的![hqz:大笨J]” “这道题又被J屎过了!!” “J这程序怎么跑这么快!J要逆袭了!” …… 描述 这一天DJ在给吾等众蒟蒻讲题,花神在一边做题无聊,就跑到了一边跟吾等众蒟蒻一起听.以下是部分摘录: 1. “J你在讲什么!” “我在讲XXX!” “哎你傻不傻的!这么麻烦,直接XXX再XXX就好了!” “……” 2. “J你XXX讲过了没?” “……” “那个都不讲你就讲这个了?哎你傻不傻的!” “……” DJ对这种情景

【BZOJ3207】花神的嘲讽计划I 可持久化线段树/莫队

看到题目就可以想到hash 然后很自然的联想到可持久化权值线段树 WA:base取了偶数 这道题还可以用莫队做,比线段树快一些 可持久化线段树: 1 #include<bits/stdc++.h> 2 #define ll long long 3 #define uint unsigned int 4 #define ull unsigned long long 5 #define inf 4294967295 6 #define N 100005 7 #define M 100005 8 #

BZOJ4241 历史研究 莫队算法 堆

欢迎访问~原文出处--博客园-zhouzhendong&AK 去博客园看该题解 题目 Description IOI国历史研究的第一人--JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. 日记中记录了连续N天发生的时间,大约每天发生一件. 事件有种类之分.第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大. JOI教授决定用如下的方法分析这些日记: 1.