bzoj 3207 可持久化线段树+hash

这道题要看出来这个做法还是比较容易说一下细节

1.因为要用hash的区间值域来建树,而hash为了不冲突要开的很大,所以值域就会比较的大,不过这道题好的一点是没有修改,所以直接离散一下就会小很多

2.hash的时候多mod (' '     ) 

3.mod 的值可以稍微取大一点

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 typedef long long ll;
  8 
  9 const ll maxn = 200010;
 10 const ll mod = (ll)1e14 + 7;
 11 const ll p = 37;
 12 
 13 ll a[maxn], b[maxn], pos[maxn], v[maxn], f[maxn], num = 0, n, m, k;
 14 
 15 ll int_get() {
 16     ll x = 0; char c = (char)getchar(); bool f = 0;
 17     while(!isdigit(c) && c != '-') c = (char)getchar();
 18     if(c == '-') c = (char)getchar(), f = 1;
 19     while(isdigit(c)) {
 20         x = x * 10 + (int)(c - '0');
 21         c = (char)getchar();
 22     }
 23     if(f) x = -x;
 24     return x;
 25 }
 26 
 27 struct node {
 28     ll data; 
 29     node *l, *r;
 30 }e[maxn * 20]; ll ne = 0;
 31 node* root[maxn];
 32 
 33 void test(node* x, ll l, ll r) {
 34     if(!x) return; 
 35     cout << l <<" "<< r << " "<< x-> data << endl;
 36     if(l ^ r) {
 37         ll mid = (l + r) >> 1;
 38         test(x-> l, l, mid), test(x-> r, mid + 1, r);
 39     }
 40 }
 41 
 42 void insert(node* &x, node* y, ll l, ll r, ll v) {
 43     if(!x) x = e + ne ++;
 44     if(l == r) x-> data = (y ? y-> data : 0) + 1; 
 45     else {
 46         ll mid = (l + r) >> 1;
 47         if(v <= mid) {
 48             if(y) x-> r = y-> r, y = y-> l;
 49             insert(x-> l, y, l, mid, v);
 50         } 
 51         else {
 52             if(y) x-> l = y-> l, y = y-> r;
 53             insert(x-> r, y, mid + 1, r, v);
 54         }
 55     }
 56 }
 57 
 58 ll ask(node* x, node* t, ll l, ll r, ll v) {
 59     if(!x) return 0;
 60     if(l == r) return x-> data - (t ? t-> data : 0); 
 61     else {
 62         ll mid = (l + r) >> 1;
 63         if(v <= mid) {
 64             if(t) t = t-> l;
 65             return ask(x-> l, t, l, mid, v);
 66         }
 67         else {
 68             if(t) t = t-> r;
 69             return ask(x-> r, t, mid + 1, r, v);
 70         }
 71     }
 72 }
 73 
 74 bool cmp(ll x, ll t) {
 75     return b[x] < b[t];
 76 }
 77 
 78 void pre(ll n) {
 79     f[0] = 1;
 80     for(ll i = 1; i <= n; ++ i) f[i] = f[i - 1] * p % mod;
 81 }
 82 
 83 ll find(ll x) {
 84     ll l = 1, r = num + 1;
 85     while(r - l > 1) {
 86         ll mid = (l + r) >> 1; 
 87         if(b[pos[mid]] <= x) l = mid;
 88         else r = mid;
 89     }
 90     return (x == b[pos[l]] ? v[pos[l]] : -1); 
 91 }
 92 
 93 void read() {
 94     n = int_get(), m = int_get(), k = int_get();
 95     pre(n);
 96     for(ll i = 1; i <= n; ++ i) a[i] = int_get();
 97     memset(b, 0, sizeof(b));
 98     for(ll i = 1; i <= k; ++ i) b[1] = (b[1] * p % mod + a[i]) % mod;
 99     for(ll j = k + 1; j <= n; ++ j) 
100         b[j - k + 1] = (((b[j - k] - a[j - k] * f[k - 1] % mod) % mod + mod) % mod * p % mod + a[j]) % mod;
101     //for(ll i = 1; i <= n - k + 1; ++ i) cout << b[i] << endl;
102     //cout << endl;
103     for(int i = 1; i <= n - k + 1; ++ i) pos[i] = i;
104     sort(pos + 1, pos + 1 + n - k + 1, cmp);
105     v[pos[1]] = ++ num;
106     for(ll i = 2; i <= n - k + 1; ++ i) {
107         if(b[pos[i]] != b[pos[i - 1]]) ++ num;
108         v[pos[i]] = num;
109     }
110     for(ll i = 1; i <= n - k + 1; ++ i) insert(root[i], root[i - 1], 1, num, v[i]);
111 }
112 
113 void sov() {
114     while(m --) {
115         ll ls, rs;
116         ls = int_get(); rs = int_get(); rs -= k - 1; 
117         ll x = 0;
118         for(ll i = 1; i <= k; ++ i) {
119             ll s = int_get(); 
120             x = (x * p % mod + s ) % mod;
121         }
122         ll c = find(x);  
123         if(c == -1 || rs < ls) printf("Yes
"); 
124         else {
125             if(ask(root[rs], root[ls - 1], 1, num, c) > 0) printf("No
");
126             else printf("Yes
");
127         }
128     }
129 }
130 
131 int main() {
132     //freopen("test.in", "r", stdin);
133     //freopen("test.out", "w", stdout);
134     read();
135     //for(int i = 1; i <= n - k + 1; ++ i) test(root[i], 1, num), cout << endl;
136     sov();
137 }
View Code
原文地址:https://www.cnblogs.com/ianaesthetic/p/4233507.html