题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3207
Hash + 可持久化线段树,并不用离散化
将原数字串hash后扔进可持久化线段树,将询问hash后查询
注意的问题:空间开40倍否则RE;mid要写成
ull mid = (l >> 1) + (r >> 1);
if ((l & 1) && (r & 1)) mid++;
以防止爆unsigned long long。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define rep(i,l,r) for(int i=l; i<=r; i++) 6 #define clr(x,y) memset(x,y,sizeof(x)) 7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre) 8 using namespace std; 9 typedef unsigned long long ull; 10 const ull INF = 18446744073709551615UL; 11 const int maxn = 200010; 12 inline int read(){ 13 int ans = 0, f = 1; 14 char c = getchar(); 15 for(; !isdigit(c); c = getchar()) 16 if (c == '-') f = -1; 17 for(; isdigit(c); c = getchar()) 18 ans = ans * 10 + c - '0'; 19 return ans * f; 20 } 21 int n,m,k,l,r,cnt=0,rt[maxn],a[maxn],tmp[maxn],son[maxn*40][2],sum[maxn*40]; 22 ull h[maxn]; 23 void insert(ull l,ull r,int x,int &y,ull v){ 24 y = ++cnt; 25 sum[y] = sum[x] + 1; 26 if (l == r) return; 27 son[y][0] = son[x][0]; son[y][1] = son[x][1]; 28 ull mid = (l >> 1) + (r >> 1); 29 if ((l & 1) && (r & 1)) mid++; 30 int d = v > mid; 31 if (d) insert(mid+1,r,son[x][1],son[y][1],v); 32 else insert(l,mid,son[x][0],son[y][0],v); 33 } 34 bool query(int x,int y,ull v){ 35 ull l = 0, r = INF; 36 while (l < r){ 37 ull mid = (l >> 1) + (r >> 1); 38 if ((l & 1) && (r & 1)) mid++; 39 int d; 40 if (v > mid) l = mid + 1, d = 1; 41 else r = mid, d = 0; 42 x = son[x][d]; y = son[y][d]; 43 } 44 return sum[y] - sum[x] == 0; 45 } 46 int main(){ 47 n = read(); m = read(); k = read(); 48 rep(i,1,n) a[i] = read(); 49 rep(i,1,n) h[i] = h[i-1] * 107 + a[i]; 50 ull p = 1; rep(i,1,k) p *= 107; 51 rep(i,k,n) insert(0,INF,rt[i-1],rt[i],h[i] - h[i-k] * p); 52 rep(i,1,m){ 53 l = read(); r = read(); 54 rep(j,1,k) tmp[j] = read(); 55 ull htmp = 0; 56 rep(j,1,k) htmp = htmp * 107 + tmp[j]; 57 printf(query(rt[l+k-2],rt[r],htmp) ? "Yes\n" : "No\n"); 58 } 59 return 0; 60 }