bzoj1014 火星人prefix

来源:互联网 发布:淘宝店铺转化率低怎么办 编辑:程序博客网 时间:2024/06/05 08:20

火星人prefix

题目背景:

bzoj1014

分析:我有一句XXX不知道当不当讲,但是真的太恶心了!!!

这道题本来的做法是对于每一个节点,维护以它为根的子树的字符串的hash值就可以了,我是用无旋treap来实现的,然后每一次合并和分割的时候,就可以直接update像上维护即可,但是当时开始的时候我的代码不断地T飞,然后我尝试优化了很多波的常数,最后发现并没有什么卵用,然后就不停地东改改西凑凑,然后最终还是T掉了,然后学长突然表示,可以把hash改成自然溢出试试,然后,就过了,当时我就表示,如果以后不卡自然溢出,我一定死都不用qnq。本体就是利用平衡树来维护当前的字符串,然后直接进行对以xy开头的两个字符串,二分长度,比对当前的hash值是否相同,每一次split相应的区间就可以了,所以询问的操作应该是二分的操作套上平衡树的操作,应该是log2n所以说,本题的最坏的复杂度应该为nlog2n(询问操作),其余操作均可以logn实现,(不过本题用treap写的确速度比较慢······)

Source

#include <cstdio>#include <algorithm>#include <string>#include <cstring>#include <iostream>#include <cmath>#include <cctype>#include <ctime>inline char read() {static const int IN_LEN = 1048576;static char buf[IN_LEN], *s, *t;if (s == t) {t = (s = buf) + fread(buf, 1, IN_LEN, stdin);if (s == t) return -1;}return *s++;}/*template<class T>inline bool R(T &x) {static char c;static bool iosig;for (c = read(), iosig = false; !isdigit(c); c = read()) {if (c == -1) return false;if (c == '-') iosig = true;}for (x = 0; isdigit(c); c = read())x = (x << 3) + (x << 1) + (c ^ '0');if (iosig) x = -x;return true;}//*/const int OUT_LEN = 1048576;char obuf[OUT_LEN], *oh = obuf;inline void writechar(char c) {if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;*oh++ = c;}template<class T>inline void W(T x) {static int buf[30], cnt;if (!x) writechar(48);else {if (x < 0) writechar('-'), x = -x;for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;while (cnt) writechar(buf[cnt--]);}}inline void flush() { fwrite(obuf, 1, oh - obuf, stdout); }///*template<class T>inline void R(T &x) {static char c;static bool iosig;for (c = getchar(), iosig = false; !isdigit(c); c = getchar())if (c == '-') iosig = true;for (x = 0; isdigit(c); c = getchar())x = (x << 3) + (x << 1) + (c ^ '0');if (iosig) x = -x;}//*/const int h = 31;const int mod = 9875321;const int MAXN = 150000 + 10;char s[MAXN];unsigned int hash_pow[MAXN];inline int get_rand() {    static int rand_seed = 495;    rand_seed += rand_seed << 1 | 1;    return rand_seed;}struct node *null;struct node {node *lc, *rc;int size, rank;unsigned int hash;char key;node() {}node(char key) : lc(null), rc(null), size(1), rank(get_rand()), hash(key - 'a' + 1), key(key) {}inline void push_down() {}inline void maintain() {size = lc->size + 1 + rc->size;hash = lc->hash + (unsigned int)(key - 'a' + 1) * hash_pow[lc->size] + (unsigned int)rc->hash * hash_pow[lc->size + 1];}} data[MAXN], *rt;int top;struct Pair {node* first;node* second;Pair(node * first, node * second) : first(first), second(second) {}Pair() {}};inline node* new_node(char key) {node *u = &data[top++];return *u = node(key), u;}inline Pair split(node *u, int k) {if (u == null) return Pair(null, null);Pair t;u->push_down();if (k <= u->lc->size) t = split(u->lc, k), u->lc = t.second, t.second = u;else t = split(u->rc, k - u->lc->size - 1), u->rc = t.first, t.first = u;return u->maintain(), t;}inline node* merge(node *u, node *v) {if (u == null) return v;if (v == null) return u;if (u->rank < v->rank) {u->push_down(), u->rc = merge(u->rc, v);return u->maintain(), u;} else {v->push_down(), v->lc = merge(u, v->lc);return v->maintain(), v;}}inline node* build(char *a, int n) {static node *stack[MAXN], *u, *pre;int top = 0;for (int i = 0; i < n; ++i) {u = new_node(a[i]), pre = null;while (top && stack[top]->rank > u->rank)stack[top]->maintain(), pre = stack[top], stack[top--] = null;if (top) stack[top]->rc = u;u->lc = pre, stack[++top] = u;}while (top) stack[top--]->maintain();return stack[1];}inline void insert(int pos, char c) {node *nr = new_node(c);Pair t = split(rt, pos);rt = merge(t.first, merge(nr, t.second));}inline void change(int pos, char c) {Pair t1 = split(rt, pos - 1), t2 = split(t1.second, 1);t2.first->key = c, t2.first->hash = c - 'a' + 1;rt = merge(t1.first, merge(t2.first, t2.second));}inline int query_hash(int pos, int length) {Pair t1 = split(rt, pos - 1), t2 = split(t1.second, length);int hash = t2.first->hash;return rt = merge(t1.first, merge(t2.first, t2.second)), hash;}inline int query_lcp(int x, int y) {int r = std::min(rt->size - x, rt->size - y) + 2, l = 0;while (l + 1 < r) {int mid = l + r >> 1;if (query_hash(x, mid) == query_hash(y, mid)) l = mid;else r = mid;}return l;}inline void pre() {hash_pow[0] = 1;for (int i = 1; i < MAXN; ++i) hash_pow[i] = hash_pow[i - 1] * h;}char s_q[3], s_key[2];int len, q, x, y, pos;inline void solve() {scanf("%s", s), len = strlen(s);null = new_node(0), null->size = null->hash = 0, rt = build(s, len);R(q);while (q--) {scanf("%s", s_q);switch (s_q[0]) {case 'Q' :R(x), R(y), W(query_lcp(x, y)), writechar('\n');break;case 'R' :R(pos), scanf("%s", s_key), change(pos, s_key[0]);break;case 'I' :R(pos), scanf("%s", s_key), insert(pos, s_key[0]);break; }}}int main() {pre();solve();flush();return 0;}

 

0 0