【 bzoj 1014 】 [JSOI2008]火星人prefix

  用平衡树瞎维护一下哈希串即可。
  不知道为啥这题写Treap这么慢= =
  P.S.提取出区间之后一定要判断是否为空区间!插入的时候计数器也要++!

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = a , _ = b ; i <= _ ; i ++)
#define per(i,a,b) for (int i = a , _ = b ; i >= _ ; i --)

#define pii pair<char , ull>
#define fir first
#define sec second

const int maxn = 100007;
const int magic1 = 13;
const int magic2 = 17;

inline int rd() {
    char c = getchar();
    while (!isdigit(c)) c = getchar() ; int x = c - '0';
    while (isdigit(c = getchar())) x = x * 10 + c - '0';
    return x;
}

#define gprintf(...) //fprintf(stderr , __VA_ARGS__)

inline char rd_ch() {
    char c = getchar();
    while (!isalpha(c)) c = getchar();
    return c;
}

typedef unsigned int ull;

inline int rnd() {
    static int rand_seed = 42071823;
    rand_seed += rand_seed << 1 | 1;
    return rand_seed;
}

ull Pow[maxn];
pii H[maxn];

int n;

char str[maxn];

namespace Treap {
    struct node {
        node *l , *r;
        int sz , pri;
        ull sum,tag;
        pii val;

        node () { }
        node (pii _key): val(_key) , pri(rnd())
            { l = r = NULL , sum = (ull) _key.fir * _key.sec , tag = 0 , sz = 1; }

        inline void upd() {
            sz = 1 , sum = (ull) val.fir * val.sec;
            if (l) sz += l->sz , sum += l->sum;
            if (r) sz += r->sz , sum += r->sum;
        }

        inline void Tag(int v) {
            sum *= Pow[v] , val.sec *= Pow[v];
            tag += v;
        }

        inline void push() {
            if (!tag) return;
            if (l) l->Tag(tag);
            if (r) r->Tag(tag);
            tag = 0;
        }
    }mem_pool[maxn] , *rt;
    int mem_top;

    typedef pair<node* , node*> data;

    inline node *newnode(pii x) {
        node *u = &mem_pool[mem_top ++];
        *u = node(x);
        return u;
    }

    inline int Size(node *u) {
        return u ? u->sz : 0;
    }

    inline ull Sum(node *u) {
        return u ? u->sum : 0;
    }

    node *join(node *u , node *v) {
        if (!u) return v;
        if (!v) return u;
        if (u->pri < v->pri) {
            u->push();
            u->r = join(u->r , v);
            u->upd();
            return u;
        } else {
            v->push();
            v->l = join(u , v->l);
            v->upd();
            return v;
        }
    }

    data split(node *u , int k) {
        if (!u) return data(NULL , NULL);
        data t;
        u->push();
        if (Size(u->l) >= k) {
            t = split(u->l , k);
            u->l  = t.sec , t.sec = u;
        } else {
            t = split(u->r , k - Size(u->l) - 1);
            u->r = t.fir , t.fir = u;
        }
        u->upd();
        return t;
    }

    pii get_kth(int k) {
        node *u = rt;
        for (;;) {
            int t = Size(u->l) + 1;
            if (t == k)
                return u->val;
            else if (t < k)
                k -= t , u = u->r;
            else
                u = u->l;
        }
    }

    ull get_sum(int l , int r) {
        data t1 = split(rt , r) , t2 = split(t1.fir , l - 1);
        ull ret = Sum(t2.sec);
        rt = join(join(t2.fir , t2.sec) , t1.sec);
        return ret;
    }

    void insert(int p , pii x) {
        data t1 = split(rt , p);
        if (t1.sec)
            t1.sec->Tag(1);
        rt = join(t1.fir , join(newnode(x) , t1.sec));
    }

    void set_val(int p , pii x) {
        data t1 = split(rt , p) , t2 = split(t1.fir , p - 1);
        t2.sec->val = x;
        t2.sec->upd();
        rt = join(join(t2.fir , t2.sec) , t1.sec);
    }

    void build(pii *a , int n) {
        static node *stack[maxn] , *u , *pre;
        stack[1] = NULL;
        int top = 0;
        rep (i , 1 , n) {
            u = newnode(a[i]);
            pre = NULL;
            while (top && stack[top]->pri > u->pri) {
                stack[top] -> upd();
                pre = stack[top --];
            }
            u->l = pre;
            if (top) stack[top]->r = u;
            stack[++ top] = u;
        }
        while (top) stack[top --]->upd();
        rt = stack[1];
    }
}

inline void init() {
    Pow[0] = 1;
    rep (i , 1 , maxn - 1) Pow[i] = Pow[i - 1] * magic1;
}

void input() {
    scanf("%s" , str + 1);
    n = strlen(str + 1);
    rep (i , 1 , n) H[i] = pii(str[i] , Pow[i - 1]);
    Treap::build(H , n);
}

inline bool same(int l1 , int r1 , int l2 , int r2 , int L) {
    if (Treap::get_sum(l1 , r1) * Pow[L] != Treap::get_sum(l2 , r2))
        return 0;
    return 1;
}

void query(int x) {
    using namespace Treap;
    int y = rd();
    if (x > y) swap(x , y);
    int l = 1 , r = n - y + 1 , L = y - x , ans = 0;
    while (l <= r) {
        int m = (l + r) >> 1;
        if (same(x , x + m - 1 , y , y + m - 1 , L))
            l = m + 1 , ans = m;
        else
            r = m - 1;
    }
    printf("%d\n" , ans);
}

void modif(int p) {
    using namespace Treap;
    char c = rd_ch();
    set_val(p , pii(c , Pow[p - 1]));
}

void inser(int p) {
    using namespace Treap;
    char c = rd_ch();
    ++ n;
    insert(p , pii(c , Pow[p]));
}

void solve() {
    int m = rd();
    rep (i , 1 , m) {
        char cmd = rd_ch();
        int x = rd();
        switch (cmd) {
            case 'Q' : query(x); break;
            case 'R' : modif(x); break;
            case 'I' : inser(x); break;
        }
    }
}

int main() {
    init();
    #ifndef ONLINE_JUDGE
        freopen("prefix1.in" , "r" , stdin);
        freopen("info.txt" , "w" , stderr);
    #endif
    input();
    solve();
    return 0;
}

你可能感兴趣的:(【 bzoj 1014 】 [JSOI2008]火星人prefix)