zoukankan      html  css  js  c++  java
  • P4036 [JSOI2008]火星人 题解

    Description

    Luogu传送门

    Solution

    考虑使用平衡树维护 hash 值。

    一个点的 sum 值表示这个点所在子树的 hash 值,那么如何更新呢?

    应该还是比较简单的吧,就是:

    \[左子树_{sum} \times (右子树_{siz} + 1) + 根_{val} \times 右子树_{siz} + 右子树_{sum} \]

    t[x].sum = t[ls(x)].sum * fx[t[rs(x)].siz + 1] + t[x].val * fx[t[rs(x)].siz] + t[rs(x)].sum;
    

    再来看如何查询,设当前询问 \(x,y\)

    考虑使用二分,我们二分一个长度 \(len\),然后查询 \(x \sim x + len - 1\)\(y \sim y + len - 1\) 的 hash 值是否相等,并更新长度 \(len\),重复此操作。

    剩下的就看代码吧。

    Code

    (厌氧程序,谨慎食用)

    (开 O2 会 WA 两个点,我也不知道为啥 QwQ,如果有哪位 dalao 知道欢迎在评论区里告诉我)

    #include <bits/stdc++.h>
    #define uint unsigned int
    #define ls(x) t[x].l
    #define rs(x) t[x].r
    
    using namespace std;
    
    namespace IO{
        inline int read(){
            int x = 0;
            char ch = getchar();
            while(!isdigit(ch)) ch = getchar();
            while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
            return x;
        }
    
        inline char readc(){
            char ch = getchar();
            while(ch < 'a' || ch > 'z') ch = getchar();
            return ch;
        }
    
        template <typename T> inline void write(T x){
            if(x > 9) write(x / 10);
            putchar(x % 10 + '0');
        }
    }
    using namespace IO;
    
    const int N = 2e5 + 10;
    int n, m;
    uint fx[N], f[N];
    char s[N], op[5];
    struct fhq_treap{
        int val, siz, wei, l, r;
        uint sum;
    }t[N];
    int root, tot;
    
    inline void pushup(int x){
        t[x].siz = t[ls(x)].siz + t[rs(x)].siz + 1;
        t[x].sum = t[ls(x)].sum * fx[t[rs(x)].siz + 1] + t[x].val * fx[t[rs(x)].siz] + t[rs(x)].sum;
    }
    
    inline void split(int x, int k, int &a, int &b){
        if(!x) return a = b = 0, void();
        if(k >= t[ls(x)].siz + 1) a = x, split(rs(x), k - t[ls(x)].siz - 1, rs(x), b);
        else b = x, split(ls(x), k, a, ls(x));
        pushup(x);
    }
    
    inline int merge(int x, int y){
        if(!x || !y) return x | y;
        if(t[x].wei <= t[y].wei){
            rs(x) = merge(rs(x), y);
            return pushup(x), x;
        }else{
            ls(y) = merge(x, ls(y));
            return pushup(y), y;
        }
    }
    
    inline int newnode(int k){
        t[++tot].val = k, t[tot].siz = 1, t[tot].wei = rand(), t[tot].sum = k;
        return tot;
    }
    
    inline void insert(int k, char ch){
        int a, b;
        split(root, k, a, b);
        root = merge(merge(a, newnode(ch - 'a' + 1)), b);
    }
    
    inline void remove(int k){
        int a, b, c;
        split(root, k, a, b);
        split(a, k - 1, a, c);
        c = merge(ls(c), rs(c));
        root = merge(merge(a, c), b);
    }
    
    inline void update(int x, char ch){
        remove(x), insert(x - 1, ch);
    }
    
    inline uint calc(int l, int r){
        int len = r - l + 1, a, b, c;
        split(root, l - 1, a, b);
        split(b, len, b, c);
        uint res = t[b].sum;
        root = merge(merge(a, b), c);
        return res;
    }
    
    inline bool check(int l, int r, int len){
        uint res1 = calc(l, l + len - 1), res2 = calc(r, r + len - 1);
        return res1 == res2;
    }
    
    inline int query(int x, int y){
        int l = 1, r = min(n - x, n - y) + 1, res;
        while(l <= r){
            int mid = (l + r) >> 1;
            if(check(x, y, mid)) l = mid + 1, res = mid;
            else r = mid - 1;
        }
        return res;
    }
    
    int main(){
        scanf("%s", s + 1);
        n = strlen(s + 1);
        fx[0] = 1;
        for(int i = 1; i < N; ++i) fx[i] = fx[i - 1] * 27;
        for(int i = 1; i <= n; ++i) insert(i, s[i]);
        m = read();
        for(int i = 1; i <= m; ++i){
            scanf("%s", op);
            if(op[0] == 'Q'){
                int x = read(), y = read();
                write(query(x, y)), puts("");
            }else if(op[0] == 'R'){
                int x = read();
                update(x, readc());
            }else{
                int x = read(); ++n;
                insert(x, readc());
            }
        }
        return 0;
    }
    

    \[\_EOF\_ \]

  • 相关阅读:
    开始几天的基本学习
    从这个博客开始我的机器学习深度学习之路
    剑指Offer:面试题3——二维数组中的查找(java实现)
    HIVE配置文件
    C++ 之旅:前言
    leetcode 349:两个数组的交集I
    python学习(三):matplotlib学习
    python学习(二):python基本语法
    Android环境搭建
    LeetCode:237
  • 原文地址:https://www.cnblogs.com/xixike/p/15730468.html
Copyright © 2011-2022 走看看