您的位置:首页 > 其它

BZOJ 3207: 花神的嘲讽计划Ⅰ

2016-05-25 20:15 369 查看
刷点水题舒缓心情

一开始没读懂题以为是查询那些数是不是都在那个区间里

于是开始写主席树,写完发现不对QAQ

题目是求那个区间里是否存在一个字串和给定串相等

由于串长是一定的,每个节点存以该节点为结尾的长度为K的字符串的哈希值

然后用主席树判断是否存在即可

(读错题后一怒之下把主席树删了写了个特技莫队,跑得还挺快的)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#include<cstdlib>
#include<ctime>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef unsigned long long ull;
const int N=100000+5;
const int p=107;
int b
;
struct Node{
int l,r,id;
ull v;
bool operator < (const Node &x)const{
return b[l]==b[x.l]?((r<x.r)^(b[l]&1)):b[l]<b[x.l];
}
}q
;
int a
,n,m,k,tot,cnt
;
ull h
,s
;
bool ans
;
bool find(ull x){
int t=lower_bound(h+k,h+1+n,x)-h;
if(t>n||h[t]!=x)return false;
return cnt[t]?1:0;
}
int main(){
//freopen("a.in","r",stdin);
scanf("%d%d%d",&n,&m,&k);
rep(i,1,n)scanf("%d",&a[i]),s[i]=s[i-1]*p+a[i];
ull t=1;rep(i,1,k)t*=p;
rep(i,k,n)h[i]=s[i]-s[i-k]*t;
sort(h+k,h+n+1);
rep(i,k,n)a[i]=lower_bound(h+k,h+1+n,s[i]-s[i-k]*t)-h;
int S=sqrt(m+0.5);
rep(i,1,n)b[i]=(i-1)/S;
rep(i,1,m){
scanf("%d%d",&q[i].l,&q[i].r);q[i].id=i;
q[i].l+=k-1;
ull ans=0;
int x;
rep(j,1,k){scanf("%d",&x);ans=ans*p+x;}
q[i].v=ans;
}
sort(q+1,q+1+m);
int ql=1,qr=0;
rep(i,1,m){
while(qr<q[i].r)cnt[a[++qr]]++;
while(ql>q[i].l)cnt[a[--ql]]++;
while(qr>q[i].r)cnt[a[qr--]]--;
while(ql<q[i].l)cnt[a[ql++]]--;
ans[q[i].id]=find(q[i].v);
}
rep(i,1,m)puts(ans[i]?"No":"Yes");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: