题解:UVA11996 Jewel Magic
题意
给你一个 01 串,要求完成以下操作:
-
单点插入。
-
单点删除。
-
区间翻转。
-
查询两点开始的 LCP。
分析
先看查询操作,如何得到 LCP 的长度?
我们可以考虑二分长度
平衡树维护哈希即可。
发现还有一个翻转操作,这时又应当如何操作?
考虑多存一个哈希记录翻转后的哈希值。
翻转操作时交换正反哈希。
Code
发一份指针版 FHQ Treap。
#include<bits/stdc++.h> using namespace std; #define lx 114 typedef uint64_t hash_t; #define maxn 400005 hash_t lev[maxn]; struct Treap { #define siz(x) (x?x->siz:0) #define hsh(x) (x?x->hsh:0) #define rhsh(x) (x?x->rhsh:0) mt19937 rnd; Treap(uint32_t s=114) { rnd.seed(s); } struct node { node *lc, *rc; uint32_t siz, id; uint8_t ch; hash_t hsh, rhsh; uint8_t rev; node(uint8_t c, uint32_t i) { id=i; lc=rc=nullptr; siz=1, hsh=rhsh=ch=c; rev=0; } node *push_up() { siz=siz(lc)+siz(rc)+1; hsh=lev[siz(rc)+1]*hsh(lc)+lev[siz(rc)]*ch+hsh(rc); rhsh=lev[siz(lc)+1]*rhsh(rc)+lev[siz(lc)]*ch+rhsh(lc); return this; } void reverse() { swap(hsh, rhsh); swap(lc, rc); rev^=1; } void push_down() { if(!rev) return; if(lc) lc->reverse(); if(rc) rc->reverse(); rev^=1; } }; node *rt; node *new_node(uint8_t c) { return new node(c, rnd()); } void split(node *x, uint32_t k, node *&l, node *&r) { if(!x) return l=r=0, void(); x->push_down(); if(siz(x->lc)<k) l=x, split(x->rc, k-siz(x->lc)-1, x->rc, r); else r=x, split(x->lc, k, l, x->lc); x->push_up(); } node *merge(node *x, node *y) { if(!x||!y) return x?x:y; if(x->id<y->id) { x->push_down(); x->rc=merge(x->rc, y); return x->push_up(); } else { y->push_down(); y->lc=merge(x, y->lc); return y->push_up(); } } void push_back(uint8_t c) { rt=merge(rt, new_node(c)); } void insert(int p, uint8_t c) { node *a, *b; split(rt, p, a, b); rt=merge(a, merge(new_node(c), b)); } void erase(int p) { node *a, *b, *c; split(rt, p-1, a, b); split(b, 1, b, c); rt=merge(a, c); } void reverse(int l, int r) { node *a, *b, *c; split(rt, l-1, a, b); split(b, r-l+1, b, c); b->reverse(); rt=merge(merge(a, b), c); } hash_t query(int l, int r) { node *a, *b, *c; split(rt, l-1, a, b); split(b, r-l+1, b, c); hash_t ret=b->hsh; rt=merge(merge(a, b), c); return ret; } }tr(114514); string s; bool chk(int p1, int p2, int l, int mxlen) { if(p1+l-1>mxlen||p2+l-1>mxlen) return 0; hash_t h1=tr.query(p1, p1+l-1); hash_t h2=tr.query(p2, p2+l-1); return h1==h2; } int LCP(int p1, int p2) { if(!tr.rt) return 0; int len=tr.rt->siz; int ret=0; for(int i=1<<20;i;i>>=1) if(chk(p1, p2, ret+i, len)) ret+=i; return ret; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); lev[0]=1; for(int i=1;i<maxn;i++) lev[i]=lev[i-1]*lx; int m; cin>>m>>m; cin>>s; for(auto c:s) tr.push_back(c); while(m--) { int op, p, x; cin>>op>>p; if(op==1) cin>>x, tr.insert(p, x^48); if(op==2) tr.erase(p); if(op==3) cin>>x, tr.reverse(p, x); if(op==4) cin>>x, cout<<LCP(p, x)<<'\n'; } }
本文作者:Jimmy-LEEE
本文链接:https://www.cnblogs.com/redacted-area/p/18379552
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步