zoukankan      html  css  js  c++  java
  • 【BZOJ 1014】 [JSOI2008]火星人prefix

    【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1014

    【题意】

    让你在线查询最长公共前缀.
    支持单节点修改;
    插入操作;

    【题解】

    /*
        伸展树会保证
        这棵树的中序遍历的结果是s[1..n]
        即整个序列;
        在进行旋转操作的时候,这个性质能被保持住;
        伸展树在维护的时候;
        每次会把需要操作的节点转到根节点;
        然后进行对应的操作;
        我们在进行
        LCQ(x,y)的时候,
        先二分枚举长度len;
        然后把
        x-1,x+len的节点编号获取a1,a2;
        y-1,y+len的节点编号也获取b1,b2;
        然后把a1转到根节点,a2放到根节点(也就是a1)的下面;
        因为x+len>x-1所以a2肯定是在a1的右儿子处;
        而这个时候a2的左子树代表的字符就是
        s[x..x+len-1]了;
        相应的对b1,b2也做同样的事情
        也能获取s[y..y+len-1];
        根据伸展树维护的hash值判断这两个子串是否相同。。
        如果相同的话,就可以让len边长一点;
        不同的话,肯定不能变长了,就变短一点呗.
        然后返回答案就好
    
        插入操作的话;
        先提取x节点,把它转到根节点的位置;
        然后再提取x+1号节点,把它转到根节点的下方
        这里x+1号节点的左儿子肯定是空的,因为x和x+1是连在一起的;
        中间不可能还有比x+1小的了;
        则把这个新插入的节点放在x+1号节点的左边.
    
        修改操作就简答多了
        直接找到那个节点;
        然后把它转到根节点去;
        再修改它的值;
        这里记住每次都把节点转到根节点就好
    
        头部和尾部都要加一个空节点;
        这样做写插入操作会好写一点吧?
    
        hash值可以搜一下RKhash;
        这里不用管它会溢出;
        你开一个unsigned long long就可以毁天灭地了;
        let it go~~
    */


    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL unsigned long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%lld",&x)
    #define which(x) (ch[fa[x]][1]==x)
    
    typedef pair<int, int> pii;
    typedef pair<LL, LL> pll;
    
    const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1 };
    const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1 };
    const double pi = acos(-1.0);
    const int N = 1e5 + 200;
    const LL seed = 131;
    
    char s[N], str[N], op[10], val[10];
    int m, n, fa[N], tot, ch[N][2], root, x, siz[N];
    LL po_w[N], has[N];
    
    void push_up(int x)
    {
        siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
        has[x] = has[ch[x][0]] + po_w[siz[ch[x][0]]] * str[x] + po_w[siz[ch[x][0]] + 1] * has[ch[x][1]];
    }
    
    int build(int l, int r, int rt)
    {
        if (l > r) return 0;
        int mid = (l + r) >> 1;
        int x = ++tot;
        fa[x] = rt; str[x] = s[mid];
        ch[x][0] = build(l, mid - 1, x);
        ch[x][1] = build(mid + 1, r, x);
        push_up(x);
        return x;
    }
    
    int Rank(int x, int k)
    {
        if (siz[ch[x][0]] >= k)
            return Rank(ch[x][0], k);
        else
            if (k == siz[ch[x][0]] + 1)
                return x;
            else
                return Rank(ch[x][1], k - siz[ch[x][0]] - 1);
    }
    
    void Rotate(int x)
    {
        int f = fa[x];
        bool k = which(x);
        ch[f][k] = ch[x][!k];
        ch[x][!k] = f;
        ch[fa[f]][which(f)] = x;
        fa[ch[f][k]] = f;
        fa[x] = fa[f];
        fa[f] = x;
        siz[x] = siz[f], has[x] = has[f];
        push_up(f);
    }
    
    void Splay(int x, int g)
    {
        while (fa[x] != g)
        {
            int f = fa[x];
            if (fa[f] == g)
            {
                Rotate(x);
                break;
            }
            if (which(x) ^ which(f))
                Rotate(x);
            else
                Rotate(f);
            Rotate(x);
        }
        if (!g) root = x;
    }
    
    void Change(int pos, char val)
    {
        int x = Rank(root, pos);
        Splay(x, 0);
        str[x] = val;
        push_up(x);
    }
    
    void Insert(int pos, char val)
    {
        int x = Rank(root, pos), y = Rank(root, pos + 1);
        Splay(x, 0), Splay(y, x);
        ch[y][0] = ++tot;
        str[tot] = val, fa[tot] = y;
        push_up(tot), push_up(y), push_up(x);
    }
    
    int lcq(int tx, int ty)
    {
        int l = 0, r = n, ans = 0;
        while (l <= r)
        {
            int mid = (l + r) >> 1;
            if (ty + mid - 1 > n + 1) //?????
            {
                r = mid - 1;
                continue;
            }
            //[tx..tx+mid-1] but (tx-1,tx+mid)
            int x = Rank(root, tx - 1), y = Rank(root, tx + mid);
            Splay(x, 0), Splay(y, x);
            LL temp1 = has[ch[y][0]];
            x = Rank(root, ty - 1), y = Rank(root, ty + mid);
            Splay(x, 0), Splay(y, x);
            if (temp1 == has[ch[y][0]])
            {
                ans = mid;
                l = mid + 1;
            }
            else
                r = mid - 1;
        }
        return ans;
    }
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        po_w[0] = 1;
        rep1(i, 1, N - 2)
            po_w[i] = po_w[i - 1] * seed;
        scanf("%s", s + 1);
        n = strlen(s + 1);
        root = build(0, n + 1, 0);
        rei(m);
        rep1(i, 1, m)
        {
            scanf("%s", op);
            if (op[0] == 'R')
            {
                scanf("%d%s", &x, val);
                Change(x + 1, val[0]);
            }
            else
                if (op[0] == 'I')
                {
                    scanf("%d%s", &x, val);
                    Insert(x + 1, val[0]);
                    n++;
                }
                else
                    if (op[0] == 'Q')
                    {
                        int x, y;
                        scanf("%d%d", &x, &y);
                        if (x > y)
                            swap(x, y);
                        if (x != y)
                            printf("%d
    ", lcq(x + 1, y + 1));
                        else
                            printf("%d
    ", n - x + 1);
                    }
        }
        return 0;
    }
  • 相关阅读:
    字典的创建以及操作
    对列表的操作
    python中列表中元素的增删改查
    pycharm中代码整体缩进
    pycharm的简介
    break,continue的区别
    python_字符串的格式化输出
    Zabbix安装图解教程
    性能瓶颈定位整体思路
    数据库监控的指标
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626586.html
Copyright © 2011-2022 走看看