BZOJ 3207: 花神的嘲諷計劃Ⅰ

刷點水題舒緩心情

一開始沒讀懂題以爲是查詢那些數是不是都在那個區間裏

於是開始寫主席樹,寫完發現不對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[N];
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[N];
int a[N],n,m,k,tot,cnt[N];
ull h[N],s[N];
bool ans[N];
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;
}
		


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章