BZOJ_3207_花神的嘲讽计划1_(Hash+主席树)

Posted 晴歌。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ_3207_花神的嘲讽计划1_(Hash+主席树)相关的知识,希望对你有一定的参考价值。

描述


http://www.lydsy.com/JudgeOnline/problem.php?id=3207

给出一个长度为\\(n\\)的串,以及\\(m\\)个长度为\\(k\\)的串,求每个长度为\\(k\\)的串在原串\\([x,y]\\)区间是否出现过.

 

分析


这道题要求对比长度为\\(k\\)的串,于是我们把这些串的Hash值都算出来,问题就转化成了求\\([x,y]\\)的区间中是否出现过某Hash值.

求区间中某一个值出现了多少次,可以用主席树.

 

p.s.

1.学习了主席树指针的写法,比数组慢好多啊...看来有必要去学一学平衡树的数组写法...不过好处是不用自己算空间...

2.这道题自己算空间的话会MLE,所以卡着空间限制就好,估计数据比较小,可以过.

 

数组:

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=200000+5,X=27;
 5 typedef unsigned long long ull;
 6 const ull INF=~0ull;
 7 int n,m,k,cnt;
 8 int a[maxn],rt[maxn];
 9 ull s[maxn],x=1;
10 struct node{ int l,r,s; }t[maxn*50];
11 inline int read(int &x){ x=0;int k=1;char c;for(c=getchar();c<\'0\'||c>\'9\';c=getchar())if(c==\'-\')k=-1;for(;c>=\'0\'&&c<=\'9\';c=getchar())x=x*10+c-\'0\';return x*=k; }
12 void update(ull l,ull r,int &pos,ull d){
13     t[++cnt]=t[pos]; pos=cnt; t[pos].s++;
14     if(l==r) return;
15     ull mid=l+(r-l)/2;
16     if(d<=mid) update(l,mid,t[pos].l,d);
17     else update(mid+1,r,t[pos].r,d);
18 }
19 bool query(int x,int y,ull l,ull r,ull d){
20     if(t[y].s-t[x].s==0) return false;
21     if(l==r) return true;
22     ull mid=l+(r-l)/2;
23     if(d<=mid) return query(t[x].l,t[y].l,l,mid,d);
24     else return query(t[x].r,t[y].r,mid+1,r,d);
25 }
26 int main(){
27     read(n); read(m); read(k);
28     for(int i=1;i<=n;i++){
29         read(a[i]);
30         s[i]=s[i-1]*X+(ull)a[i];
31     }
32     for(int i=1;i<=k;i++) x*=X;
33     for(int i=k;i<=n;i++) rt[i]=rt[i-1], update(0ull,INF,rt[i],s[i]-s[i-k]*x);
34     for(int i=1;i<=m;i++){
35         ull hash=0; bool ans;
36         int l,r; read(l); read(r);
37         for(int j=1,t;j<=k;j++)  hash=hash*X+read(t);
38         if(r+1-l<k) ans=false;
39         else ans=query(rt[l+k-2],rt[r],0ull,INF,hash);
40         ans?puts("No"):puts("Yes");
41     }
42     return 0;
43 }
View Code

 

 

指针:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=200000+5,X=27;
 5 typedef unsigned long long ull;
 6 const ull INF=~0ull;
 7 int n,m,k,cnt;
 8 int a[maxn];
 9 ull s[maxn],x=1;
10 struct node{
11     node* l,* r; int s;
12     node(){}
13     node(node *l,node* r,int s):l(l),r(r),s(s){}
14 }* rt[maxn],* null;
15 inline int read(int &x){ x=0;int k=1;char c;for(c=getchar();c<\'0\'||c>\'9\';c=getchar())if(c==\'-\')k=-1;for(;c>=\'0\'&&c<=\'9\';c=getchar())x=x*10+c-\'0\';return x*=k; }
16 node* update(node* t,ull l,ull r,ull d){
17     if(l==r) return new node(null,null,t->s+1);
18     ull mid=l+(r-l)/2;
19     if(d<=mid) return new node(update(t->l,l,mid,d),t->r,t->s+1);
20     else return new node(t->l,update(t->r,mid+1,r,d),t->s+1);
21 }
22 bool query(node* x,node* y,ull l,ull r,ull d){
23     if(y->s-x->s==0) return false;
24     if(l==r) return true;
25     ull mid=l+(r-l)/2;
26     if(d<=mid) return query(x->l,y->l,l,mid,d);
27     else return query(x->r,y->r,mid+1,r,d);
28 }
29 int main(){
30     read(n); read(m); read(k);
31     null=new node;
32     null->l=null, null->r=null, null->s=0;
33     for(int i=1;i<=n;i++){
34         read(a[i]);
35         s[i]=s[i-1]*X+(ull)a[i];
36     }
37     for(int i=1;i<=k;i++) x*=X;
38     rt[k-1]=new node(null,null,0);
39     for(int i=k;i<=n;i++) rt[i]=update(rt[i-1],0ull,INF,s[i]-s[i-k]*x);
40     for(int i=1;i<=m;i++){
41         ull hash=0; bool ans;
42         int l,r; read(l); read(r);
43         for(int j=1,t;j<=k;j++)  hash=hash*X+read(t);
44         if(r+1-l<k) ans=false;
45         else ans=query(rt[l+k-2],rt[r],0ull,INF,hash);
46         ans?puts("No"):puts("Yes");
47     }
48     return 0;
49 }
View Code

 

以上是关于BZOJ_3207_花神的嘲讽计划1_(Hash+主席树)的主要内容,如果未能解决你的问题,请参考以下文章

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

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

BZOJ3207 花神的嘲讽计划

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

BZOJ3207 花神的嘲讽计划Ⅰ

bzoj 3207 花神的嘲讽计划Ⅰ