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

 

转载于:https://www.cnblogs.com/Sunnie69/p/5602182.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值