bzoj1014 [JSOI2008]火星人prefix

splay的区间操作(区间表示),Hash离散,二分答案

Hash值(代码中是RK的hash函数)是一个节点域,除此就没什么特别的了

#include<bits/stdc++.h>
using namespace std;

inline int get_int()    {
    char c; int res = 0;
    while(!isdigit(c = getchar()));
    for(res = c - '0'; isdigit(c = getchar()); )
        res = res * 10 + c - '0';
    return res;
}
inline char get_ch()    {
    char c;
    while(!isalpha(c = getchar()));
    return c;
}

typedef unsigned int uint;

const int MAXN = 100000;
const uint seed = 131;

uint Pow[MAXN + 10];

struct node {
    int key, size; uint RK;
    node *c[2];
    node():key(0), size(0), RK(0) { c[0] = c[1] = this; }
    node(uint key, node *_c0, node *_c1):key(key) { c[0] = _c0; c[1] = _c1; }
    node *rz() { return RK = (c[0]->RK * seed + (uint)key) * Pow[c[1]->size] + c[1]->RK, size = c[0]->size + c[1]->size + 1, this; }
}   Tnull, *null = &Tnull;

struct splay    {
    node *root;
    void zig(bool d)    {
        node *t = root->c[d];
        root->c[d] = null->c[d];
        null->c[d] = root;
        root = t;
    }
    void zigzig(bool d) {
        node *t = root->c[d]->c[d];
        root->c[d]->c[d] = null->c[d];
        null->c[d] = root->c[d];
        root->c[d] = null->c[d]->c[!d];
        null->c[d]->c[!d] = root->rz();
        root = t;
    }
    void finish(bool d) {
        node *t = null->c[d], *p = root->c[!d];
        while(t != null)    {
            t = null->c[d]->c[d];
            null->c[d]->c[d] = p;
            p = null->c[d]->rz();
            null->c[d] = t;
        }
        root->c[!d] = p;
    }
    void select(int k)   {
        int t;
        while(1)    {
            bool d = k > (t = root->c[0]->size);
            if(k == t || root->c[d] == null)    break;
            if(d) k -= t + 1;
            bool dd = k > (t = root->c[d]->c[0]->size);
            if(k == t || root->c[d]->c[dd] == null) { zig(d); break; }
            if(dd) k -= t + 1;
            d != dd ? zig(d), zig(dd) : zigzig(d);
        }
        finish(0), finish(1);
        root->rz();
    }
    void modify(int k, int x)   {
        select(k - 1);
        root->key = x;
        root->rz();
    }
    void ins(int k, int x)  {
        select(k - 1);
        node* oldroot = root;
        root = new node(x, oldroot->c[0], oldroot);
        oldroot->c[0] = null;
        oldroot->rz();
        root->rz();
    }
    node *split(int st, int len)   {
        select(st - 2);
        node *oldroot = root;
        root = oldroot->c[1];
        select(len);
        oldroot->c[1] = root->rz();
        swap(root, oldroot);
        return oldroot->c[0];
    }
}   sp;

int ops;
char buf[MAXN + 10];

node *Build(int l, int r)   {
    if(l > r) return null;
    int mid = l + (r - l) / 2;
    return (new node(buf[mid], Build(l, mid - 1), Build(mid + 1, r)))->rz();
}

int query(int st1, int st2) {
    int L = 0, R = sp.root->size - max(st1, st2);
    while(L < R)    {
        int M = L + (R - L + 1) / 2;
        uint a = sp.split(st1, M)->RK;
        uint b = sp.split(st2, M)->RK;
        if(a == b)  L = M;
        else R = M - 1;
    }
    return L;
}

int main()  {
    Pow[0] = 1;
    for(int i = 1; i <= MAXN; i++)  Pow[i] = Pow[i - 1] * seed;

    int len;

    scanf("%s%d", buf + 1, &ops);
    len = strlen(buf + 1);

    buf[0] = buf[len + 1] = '&';
    buf[len + 2] = 0;

    sp.root = Build(0, len + 1);

    for(int i = 1; i <= ops; i++)   {
        char opt; int x, y; char c;
        opt = get_ch();
        if(opt == 'Q')  {
            x = get_int(); y = get_int();
            printf("%d\n", query(x + 1, y + 1));
        }
        else if(opt == 'R') {
            x = get_int(); c = get_ch();
            sp.modify(x + 1, c);
        }
        else {
            x = get_int(); c = get_ch();
            sp.ins(x + 2, c);
        }
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值