UVA 11996 Splay + LCP + Hash + 区间翻转 插入 删除
来源:互联网 发布:淘宝好评返现素材 编辑:程序博客网 时间:2024/06/03 12:26
【题意】给出一个长度为n的01串,有m个操作。操作有以下几种:
1 p c在第p个字符后插入c
2 p 删除第p个字符
3 p1 p2 翻转p1到p2的字符串
4 p1 p2 求从p1开始和p2开始的两个后缀的LCP
【解题方法】
【PS】这题有点恶心,在LCP提取区间的时候,把Rotateto写成了Rotate,查了半天错才知道。
【代码君】
////Created by just_sort 2016/10/15//Copyright (c) 2016 just_sort.All Rights Reserved//#include <set>#include <map>#include <queue>#include <stack>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;typedef unsigned long long uLL;const int pp = 239641;const int maxn = 555555;uLL p[maxn],Hash[maxn][2];char s[maxn];int ch[maxn][2],pre[maxn],val[maxn],sz[maxn],rev[maxn],root,tot;void Treaval(int x) { if(x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]); Treaval(ch[x][1]); }}void debug() {printf("%d\n",root);Treaval(root);}void Newnode(int &rt,int fa,int k){ rt = ++tot; ch[rt][0] = ch[rt][1] = rev[rt] = 0; sz[rt] = 1; pre[rt] = fa; Hash[rt][0] = Hash[rt][1] = val[rt] = k;}void pushup(int rt){ sz[rt] = sz[ch[rt][0]] + sz[ch[rt][1]] + 1; int len = sz[ch[rt][0]]; Hash[rt][0] = Hash[ch[rt][0]][0] + val[rt]*p[len] + Hash[ch[rt][1]][0]*p[len+1]; len = sz[ch[rt][1]]; Hash[rt][1] = Hash[ch[rt][1]][1] + val[rt]*p[len] + Hash[ch[rt][0]][1]*p[len+1];}void f(int rt){ if(!rt) return ; swap(ch[rt][0], ch[rt][1]); swap(Hash[rt][0], Hash[rt][1]); rev[rt] ^= 1;}void pushdown(int rt){ if(rev[rt]){ f(ch[rt][0]); f(ch[rt][1]); rev[rt] = 0; }}void Rotate(int x,int kind){ int y = pre[x]; pushdown(y); pushdown(x); ch[y][kind^1] = ch[x][kind]; pre[ch[x][kind]] = y; if(pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; pre[x] = pre[y]; ch[x][kind] = y; pre[y] = x; pushup(y);}void Splay(int r,int goal){ pushdown(r); while(pre[r]!=goal) { if(pre[pre[r]]==goal) { Rotate(r,ch[pre[r]][0]==r); pushdown(pre[r]); pushdown(r); } else { pushdown(pre[pre[r]]); pushdown(pre[r]); pushdown(r); int y=pre[r]; int kind=(ch[pre[y]][0]==y); if(ch[y][kind]==r) { Rotate(r,!kind); Rotate(r,kind); } else { Rotate(y,kind); Rotate(r,kind); } } } pushup(r); if(goal==0) root=r;}void RotateTo(int k, int goal){ int rt = root; pushdown(rt); while(sz[ch[rt][0]] != k) { if(sz[ch[rt][0]] > k) rt = ch[rt][0]; else{ k -= (sz[ch[rt][0]] + 1); rt = ch[rt][1]; } pushdown(rt); } Splay(rt,goal);}void Insert(int k, int c){ RotateTo(k, 0); RotateTo(k+1, root); int rt = ch[root][1]; Newnode(ch[rt][0], rt, c); pushup(rt); pushup(root);}void Delete(int p){ RotateTo(p-1, 0); RotateTo(p+1, root); int rt =ch[root][1]; ch[rt][0] = 0; pushup(rt); pushup(root);}void Reverse(int L, int R){ RotateTo(L-1, 0); RotateTo(R+1, root); f(ch[ch[root][1]][0]); pushup(ch[root][1]); pushup(root);}bool judge(int x,int y,int len){ uLL xval, yval; RotateTo(x-1, 0); if(sz[ch[root][1]] - 1 < len) return 0; RotateTo(x+len, root); int rt = ch[ch[root][1]][0]; xval = Hash[rt][rev[rt]]; RotateTo(y-1, 0); if(sz[ch[root][1]] - 1 < len) return 0; RotateTo(y+len, root); rt = ch[ch[root][1]][0]; yval = Hash[rt][rev[rt]]; return xval == yval;}int Lcp(int x,int y){ int L = 1, R = sz[root] - 1; if(!judge(x, y, 1)) return 0; while(R - L > 1) { int mid = (L + R)>>1; if(judge(x, y, mid)) L = mid; else R = mid; } return L;}void Build(int l, int r,int &rt, int fa){ if(l > r) return; int m = (l + r)>>1; Newnode(rt, fa, s[m] - '0'); Build(l, m-1, ch[rt][0], rt); Build(m+1, r, ch[rt][1], rt); pushup(rt);}void Init(int n){ ch[0][0] = ch[0][1] = sz[0] = 0; Hash[0][0] = Hash[0][1] = 0; rev[0] = pre[0] = val[0] = 0; root = tot = 0; Newnode(root, 0, 0); Newnode(ch[root][1], root, 0); Build(0, n-1, ch[ch[root][1]][0], ch[root][1]); pushup(ch[root][1]); pushup(root);}int main(){ p[0] = 1; for(int i = 1; i < maxn; i++) p[i] = p[i-1] * pp; int n, m; while(scanf("%d%d",&n,&m) != EOF) { scanf("%s", s); Init(n); //debug(); int op, p1, p2, c; for(int i = 1; i <= m; i++) { scanf("%d%d", &op, &p1); if(op == 1) { scanf("%d", &c); Insert(p1, c); //debug(); } else if(op == 2){ Delete(p1); //debug(); } else if(op == 3){ scanf("%d", &p2); Reverse(p1,p2); //debug(); } else{ scanf("%d", &p2); int ans = Lcp(p1, p2); printf("%d\n", ans); } } } return 0;}
0 0
- UVA 11996 Splay + LCP + Hash + 区间翻转 插入 删除
- 新技能:splay支持区间翻转,区间插入,区间删除
- 【数据结构SPLAY】splay区间翻转,区间和查询,区间插入,区间删除,区间修改
- hdu 3487 Play with Chain splay 区间翻转,插入,删除
- hdu 3487 区间 翻转 切割 插入 splay
- UVA 11922 Splay区间翻转+分裂+合并
- POJ 题目3580 SuperMemo(Splay Tree区间加,区间翻转,区间右移,插入删除,区间最小值)
- splay区间翻转及删除区间,平移区间
- UVA 11922 Permutation Transformer Splay 区间翻转 + 区间合并
- UVA 11996 Jewel Magic (splay求两个后缀的LCP)
- hdu3487 (splay伸展树 区间翻转,切割,插入)
- Splay区间翻转
- 区间翻转问题 Splay
- UVA 11922 Permutation Transformer (Splay 区间翻转 + 复制粘贴)
- Uva 3961 Robotic Sort(Splay区间翻转)
- UVA 11996 Jewel Magic Splay+Hash
- UVA 11996 Jewel Magic splay+字符串hash
- hdu 1890 splay区间翻转
- android绘制实心圆、空心圆
- Redis Sentinel机制与用法(一)
- VS2008调试技术
- HDU ACM 11 2040 亲和数
- wamp 的Redis 环境搭建以及phpredis扩展
- UVA 11996 Splay + LCP + Hash + 区间翻转 插入 删除
- Redis Sentinel 机制与用法(二)
- MapReduce代码实例练习
- 网络流——最大流打二分图、最小割
- 分享一个前端学习的网站
- JAVA中文件上传下载
- 【NOIP2016提高A组模拟10.15】最大化
- RGB HSV HSB HSL
- Linux获取root,提示Authentication failure