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 }
指针:
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 }
以上是关于BZOJ_3207_花神的嘲讽计划1_(Hash+主席树)的主要内容,如果未能解决你的问题,请参考以下文章