zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    内联函数和宏
    C++内联函数与宏定义
    C++函数声明和定义深度解析
    C++中的头文件和源文件
    国外程序员整理的 C++ 资源大全
    c语言中的字符数组与字符串
    iOS应用架构谈(二):View层的组织和调用方案(中)
    iOS应用架构谈(一):架构设计的方法论
    解决xib约束冲突
    tableView设置首尾
  • 原文地址:https://www.cnblogs.com/ianaesthetic/p/4233507.html
Copyright © 2011-2022 走看看