bzoj 3207 hash + 可持久化数据结构

思路: 把长度为K 的串 hash 之后,就变成 查询区间中有没有某个数。

不知道为什么  RKHash 的思想 hash 时一直不过, 暴力 O(NK) hash 时 可以通过。



// 。。。bzoj 3207  打死不过  给跪了

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
const double eps = 1e-9;
#define LL long long 
#define pb push_back
const int maxn = 201000;
int n, q,k;
LL t[maxn]; 
const LL P = 107;
LL myhash(int l,int r){
 	LL ret = 0;
 	for(int i=l;i<=r;i++){
 		ret *= P;
 		ret += t[i];
 	}
 	return ret;
}
int tot;
LL tmp[maxn];
map<LL,int>mp;
map<LL,int>::iterator it;
struct Node{
	Node *l ,*r;
	int sum;
};
struct Seg{
	Node nodes[maxn*40];
	Node *null;
	int C;
	Node *root[maxn];
	void init(){
		 C= 0;
		 null = &nodes[C++];
		 null ->l = null->r = null;
		 null->sum = 0 ;
		 root[0] = null;
	}
	 Node *update(int pos,int left ,int right,Node *root){
		  Node *rt = &nodes[C++];
		  rt->l = root->l ;
		  rt->r = root->r;
		  rt->sum = root->sum;
		  if(left==right){
		  	   rt->sum ++;
		  	   return rt;
		  }
		  int mid = (left +  right)>>1;
 		  if(pos<=mid){
 		  	 rt->l = update(pos,left,mid,root->l);
 		  }else{
 		  	rt->r = update(pos,mid+1,right,root->r);
 		  }
 		  rt->sum = rt->l->sum + rt->r->sum;
 		  return rt;
	}
	void solve(){
		for(int i=1;i<=tot;i++){
			root[i] = update(mp[tmp[i]],1,tot,root[i-1]);
		}
	}
	int query(int pos,int left,int right,Node *root){
		 if(left == right)return root->sum ;
		 int mid = (left +right)>>1;
		 if(pos<=mid){
		 	return query(pos,left,mid,root->l);
		 }else{
		 	return query(pos,mid+1,right,root->r);
		 }
	}
	int query(int q,int L,int R){
		if(R<=L)return 0;
		int ans = query(q,1,tot,root[R]) - query(q,1,tot,root[L-1]);
		return ans;
	}
}S;
void solve1(){
	S.init();
	tot = n -k +1;
	for(int i=1;i<=tot;i++){
          tmp[i] = myhash(i,i+k-1);
	}
	mp.clear();
	for(int i=1;i<=tot;i++){
	       	mp[tmp[i]]=1;
	}
	int Q = 0;
	for(it = mp.begin();it!=mp.end();it++){
		Q++;
		it->second = Q;
	}
	S.solve();
	
}
int x,y;
void solve(){
    for(int i=1;i<=q;i++){
    	  scanf("%d%d",&x,&y);
    	  for(int j=1;j<=k;j++){
    	  	scanf("%lld",&t[j]);
    	  }
    	   LL hash = myhash(1,k);
    	  //cout << hash<<endl;
    	  if(mp.find(hash)==mp.end()){
    	  	 puts("Yes");  
    	  }else{
    	  	 int ans = S.query(mp[hash],x,y-k+1);
    	  //	 cout << ans << "ans "<<endl;
    	  	 if(ans>0){
    	  	 	 puts("No");
    	  	 }else{
    	  	 	puts("Yes");
    	  	 }
    	  }
    	  
    }
}
int main(){
    while(~scanf("%d%d%d",&n,&q,&k)){
    	 for(int  i =1;i<=n;i++){
    	 	 scanf("%lld",&t[i]);
    	 }
    	 solve1();
    	 solve();
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值