• 【JSOI2008】火星人 (哈希+Splay)


    题目

    这种含有修改操作的就难以用后缀数组实现了,求LCP这种区间相等的类型可以想到用hash判断,同时LCP的答案大小符合二分条件可以二分求出,如果只有修改可以用线段树维护,因为还有有插入操作所以想到平衡树。

    #include<cstdio>
    const int N = 2e5 + 5;
    const int base = 237;
    typedef unsigned long long ull;
    ull pow[N];
    
    struct Splay{   
        #define ls p[u].son[0]
        #define rs p[u].son[1]
        #define maxn N
    
        int root = 1, cnt = 2;
        struct Node{
            int fa, size, len;    // size是子树大小,len是除去虚点的子树大小 
            ull hash, val;
            int son[2]; 
        }p[maxn];
    
        inline int identify(int u){
            return p[p[u].fa].son[1] == u;
        }
    
        inline void update(int u){
            p[u].size = p[ls].size + p[rs].size + 1;
            p[u].len = p[ls].len + p[rs].len + (u > 2);  // 判断u > 2是为了除去虚点的影响 
            p[u].hash = (p[ls].hash * base + p[u].val) * pow[p[rs].len] + p[rs].hash;
        }
    
        void rotate(int u){
            int f = p[u].fa,  gf = p[f].fa,  sta = identify(u),  sta_f = identify(f);
            p[f].son[sta] = p[u].son[sta ^ 1];
            p[p[f].son[sta]].fa = f;
            p[u].son[sta^1] = f,  p[f].fa = u,  p[u].fa = gf;
            p[gf].son[sta_f] = u;
            update(f);
        }
    
        void splay(int u, int goal){
            for(int f; (f = p[u].fa) && (f != goal); rotate(u)){
                if(p[f].fa != goal)  rotate(identify(u) == identify(f) ? f : u);
            }
            if(!goal)  root = u; 
            update(u);
        }
    
        ull Hash(int u, int len){
            int L = find_Kth(u), R = find_Kth(u +  len + 1);
            splay(L, 0),  splay(R, L);
            return p[p[R].son[0]].hash;
        }
    
        int LCQ(int x, int y){
            int L = 0, R = cnt - 1 - y, ans;
            while(L <= R){
                int mid = (L + R) >> 1;
                if(Hash(x, mid) == Hash(y, mid))  L = mid + 1, ans = mid;
                else  R = mid - 1;
            }
            return ans;
        }
    
        int find_Kth(int k){
            int u = root;
            while(1){
                if(p[ls].size + 1 == k)  return u;
                if(p[ls].size >= k)  u = ls;
                else  k -= p[ls].size + 1,  u = rs;
            }
        }
    
        void insert(int u, int val){
            int L = find_Kth(u),  R = find_Kth(u + 1);
            splay(L, 0), splay(R, L);
            p[++cnt].val = val,  p[R].son[0] = cnt,  p[cnt].fa = R;
            splay(cnt, 0);
        }
    
        void modify(int x, int val){
            int L= find_Kth(x),  R = find_Kth(x + 2);
            splay(L, 0),  splay(R, L);
            p[p[R].son[0]].val = val;
            update(p[R].son[0]),  update(R),  update(L);
        }
    }Tree;
    
    int m, x, y;
    char s[N], opt[2];
    
    int main(){
        scanf("%s%d", s + 1, &m);
        pow[0] = 1;
        for(int i = 1; i < N; ++i)  pow[i] = pow[i - 1] * base;
        // 插入两个虚点作为序列的左右端点,方便插入、查找等操作 
        Tree.p[1].son[1] = 2, Tree.p[2].fa = 1; 
        Tree.update(1),  Tree.update(2);    
        for(int i = 1; s[i]; ++i)  Tree.insert(i, s[i]);
        while(m--){
            scanf("%s", opt);
            if(opt[0] == 'Q'){
                scanf("%d%d", &x, &y);
                if(x > y)  x ^= y ^= x ^= y;
                printf("%d
    ", Tree.LCQ(x, y));
            }
            else if(opt[0] == 'R'){
                scanf("%d%s", &x, opt);
                Tree.modify(x, opt[0]);
            }
            else{
                scanf("%d%s", &x, opt);
                Tree.insert(x + 1, opt[0]);
            }
        }
        return 0;
    }
    你只有十分努力,才能看上去毫不费力。
  • 相关阅读:
    字段修改名称
    coercing to Unicode: need string or buffer, geoprocessing value object found
    为什么ArcGIS 10.3导出 Shapefile的字段名会被截断成3个汉字?解决方法如下
    arcgis python 使用光标和内存中的要素类将数据加载到要素集 学习:http://zhihu.esrichina.com.cn/article/634
    arcgis python 获得arcgis安装版本和安装位置
    arcgis python 不知道一个工具怎么用
    arcgis 地理坐标系 699个,投影坐标系是4767
    arcgis python 参数类型和含义
    win10 svn commit无响应
    新建网站与新建Asp.Net Web 应用程序的区别
  • 原文地址:https://www.cnblogs.com/214txdy/p/14045468.html
Copyright © 2020-2023  润新知