bzoj 1014伸展树 模板题

来源:互联网 发布:烟台plc编程 编辑:程序博客网 时间:2024/06/05 10:06
#include<iostream>#include<cstdio>#include<algorithm>#include<string>using  namespace std;long long wei[100010];char s[100010];int n;void init()//这是针对本题的操作并无通用性{wei[0] = 1;for (int i = 1; i < 100010; i++){wei[i] = (wei[i - 1] * 26) % 2333333333;}}//写splaytree的时候关键是要和0点撇清关系。。。struct splaytree//从这开始是splay 模板{int fa, son[2], size, worth,num;unsigned long long value;splaytree(){fa = son[0] = son[1] = size = worth = value = 0;}};splaytree node[250010];void update(splaytree &k){k.size = 1 + node[k.son[0]].size + node[k.son[1]].size;k.value =(k.worth*wei[node[k.son[0]].size] + node[k.son[0]].value + node[k.son[1]].value*wei[node[k.son[0]].size + 1]) % 2333333333;}int link(splaytree &k, int d, int kid){k.son[d] = kid;if (kid)//撇清关系node[kid].fa =k.num;return k.num;}int getlr(splaytree &k){return node[k.fa].son[1] ==k.num;}int tot = 0;int root;int newnode(int worth){tot++;node[tot].worth = node[tot].value = worth;node[tot].size = 1;node[tot].num = tot;return tot;}void rot(int x){int fa = node[x].fa;int gfa = node[fa].fa;int dx = getlr(node[x]);int dfa =getlr(node[fa]);link(node[x],dx ^ 1,link(node[fa],dx, node[x].son[dx ^ 1]));if (gfa)link(node[gfa],dfa, x);elsenode[x].fa = gfa;update(node[fa]);}void newsplay(int x,int to){while (node[x].fa&&node[x].fa!=to)//这易错因为node[x].fa又阔能为空然后to不空这样就有bug 了。。。{if (node[node[x].fa].fa!=to)getlr(node[node[x].fa]) == getlr(node[x]) ? rot(node[x].fa) : rot(x);rot(x);}update(node[x]);if(to==0)root = x;//这是易错的,因为如果不是转到root是不能修改root的}int build(int l, int r){//cout << "sds" << endl;if (l > r)return 0;int mid = (l + r) >> 1;int num = newnode(s[mid]-'a');link(node[num],0, build(l, mid - 1));link(node[num],1, build(mid + 1, r));update(node[num]);if (l == 0 && r == n)root = num;return num;}int find(int size){int temp = root;while (temp != 0){if (node[node[temp].son[0]].size >= size)temp = node[temp].son[0];else{size -= node[node[temp].son[0]].size;if (size == 1)return temp;size--;temp = node[temp].son[1];}}return 0;}//这结束模板void insert(int pos,char kid)//以下是针对本题的操作{int kidnum = newnode(kid - 'a');if (pos == 0 || pos == node[root].size){int k;pos == 0 ? (k = find(1)) : (k = find(node[root].size));newsplay(k, 0);pos == 0 ? link(node[k],0, kidnum) : link(node[k],1, kidnum);update(node[k]);}else{int l = pos;int r = pos + 1;int nodel = find(l);int noder = find(r);newsplay(nodel, 0);newsplay(noder, root);link(node[noder],0, kidnum);for (int i = noder; i != 0; i = node[i].fa)update(node[i]);}}unsigned long long findvalue(int l, int r){if (l == 1&&r!=node[root].size){int end = find(r + 1);newsplay(end, 0);return node[node[root].son[0]].value;}if (r == node[root].size&&l!=1){int begin = find(l - 1);newsplay(begin, 0);return node[node[root].son[1]].value;}if (l == 1 && r == node[root].size){return node[root].value;}l = find(l - 1);r = find(r +1);newsplay(l, 0);newsplay(r, root);return node[node[r].son[0]].value;}int com(int first, int second){int l = 0;int r = min(node[root].size - first + 1, node[root].size - second + 1);int mid = r;//cout << "r:" << r << " " << "l:" << l << endl;while ((r-l)>1){unsigned long long p1 = findvalue(first, first + mid - 1);unsigned long long p2 = findvalue(second, second + mid - 1);if (p1 == p2)l = mid;elser = mid - 1;mid = (l + r) >> 1;}unsigned long long p1 = findvalue(first, first + r- 1);unsigned long long p2 = findvalue(second, second + r - 1);if (p1 != p2)return l;elsereturn r;}void change(int pos, char worth){pos = find(pos);node[pos].worth = worth - 'a';update(node[pos]);newsplay(pos, 0);}int main(){int i;for ( i = 0;; i++){scanf("%c", &s[i]);if (s[i] == '\n')break;}n = i - 1;init();build(0, n);int m;scanf("%d", &m);for (int i = 0; i < m; i++){//cout << i << endl;char c; getchar();scanf("%c", &c);if (c == 'Q'){int l, r;scanf("%d%d", &l, &r);int ans = com(l, r);printf("%d\n", ans);}if (c == 'R'){int l;char c;scanf("%d", &l);getchar();scanf("%c", &c);change(l, c);}if (c == 'I'){int l;char c;scanf("%d", &l);getchar();scanf("%c", &c);insert(l, c);}}return 0;}