邝斌的ACM模板(伸展树(splay tree))
来源:互联网 发布:用js做一个登录界面 编辑:程序博客网 时间:2024/06/05 16:41
本博客整理自邝斌的ACM模板
3.4、伸展树(splay tree)
题目:维修数列。
经典题,插入、删除、修改、翻转、求和、求和最大的子序列
#define Key_value ch[ch[root][1]][0]const int MAXN = 500010;const int INF = 0x3f3f3f3f;int pre[MAXN],ch[MAXN][2],key[MAXN],size[MAXN];int root,tot1;int sum[MAXN],rev[MAXN],same[MAXN];int lx[MAXN],rx[MAXN],mx[MAXN];int s[MAXN],tot2;//内存池和容量int a[MAXN];int n,q;//debug部分**********************************void Treavel(int x){ if(x) { Treavel(ch[x][0]); printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d\n",x,ch[x][0],ch[x][1],pre[x],size[x]); Treavel(ch[x][1]); }}void debug(){ printf("root:%d\n",root); Treavel(root);}//以上是debug部分**************************************void NewNode(int &r,int father,int k){ if(tot2) r = s[tot2--];//取的时候是tot2--,存的时候就是++tot2 else r = ++tot1; pre[r] = father; ch[r][0] = ch[r][1] = 0; key[r] = k; sum[r] = k; rev[r] = same[r] = 0; lx[r] = rx[r] = mx[r] = k; size[r] = 1;}void Update_Rev(int r){ if(!r)return; swap(ch[r][0],ch[r][1]); swap(lx[r],rx[r]); rev[r] ^= 1;}void Update_Same(int r,int v){ if(!r)return; key[r] = v; sum[r] = v*size[r]; lx[r] = rx[r] = mx[r] = max(v,v*size[r]); same[r] = 1;}void push_up(int r){ int lson = ch[r][0], rson = ch[r][1]; size[r] = size[lson] + size[rson] + 1; sum[r] = sum[lson] + sum[rson] + key[r]; lx[r] = max(lx[lson],sum[lson] + key[r] + max(0,lx[rson])); rx[r] = max(rx[rson],sum[rson] + key[r] + max(0,rx[lson])); mx[r] = max(0,rx[lson]) + key[r] + max(0,lx[rson]); mx[r] = max(mx[r],max(mx[lson],mx[rson]));}void push_down(int r){ if(same[r]) { Update_Same(ch[r][0],key[r]); Update_Same(ch[r][1],key[r]); same[r] = 0; } if(rev[r]) { Update_Rev(ch[r][0]); Update_Rev(ch[r][1]); rev[r] = 0; }}void Build(int &x,int l,int r,int father){ if(l > r)return; int mid = (l+r)/2; NewNode(x,father,a[mid]); Build(ch[x][0],l,mid-1,x); Build(ch[x][1],mid+1,r,x); push_up(x);}void Init(){ root = tot1 = tot2 = 0; ch[root][0] = ch[root][1] = size[root] = pre[root] = 0; same[root] = rev[root] = sum[root] = key[root] = 0; lx[root] = rx[root] = mx[root] = -INF; NewNode(root,0,-1); NewNode(ch[root][1],root,-1); for(int i = 0; i < n; i++) scanf("%d",&a[i]); Build(Key_value,0,n-1,ch[root][1]); push_up(ch[root][1]); push_up(root);} //旋转,0为左旋,1为右旋void Rotate(int x,int kind){ int y = pre[x]; push_down(y); push_down(x); ch[y][!kind] = 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; push_up(y);}//Splay调整,将r结点调整到goal下面void Splay(int r,int goal){ push_down(r); while(pre[r] != goal) { if(pre[pre[r]] == goal) { push_down(pre[r]); push_down(r); Rotate(r,ch[pre[r]][0] == r); } else { push_down(pre[pre[r]]); push_down(pre[r]); push_down(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); } } } push_up(r); if(goal == 0) root = r;}int Get_kth(int r,int k){ push_down(r); int t = size[ch[r][0]] + 1; if(t == k)return r; if(t > k)return Get_kth(ch[r][0],k); else return Get_kth(ch[r][1],k-t);}//在第pos个数后面插入tot个数void Insert(int pos,int tot){ for(int i = 0; i < tot; i++)scanf("%d",&a[i]); Splay(Get_kth(root,pos+1),0); Splay(Get_kth(root,pos+2),root); Build(Key_value,0,tot-1,ch[root][1]); push_up(ch[root][1]); push_up(root);}//删除子树void erase(int r){ if(!r)return; s[++tot2] = r; erase(ch[r][0]); erase(ch[r][1]);}//从第pos个数开始连续删除tot个数void Delete(int pos,int tot){ Splay(Get_kth(root,pos),0); Splay(Get_kth(root,pos+tot+1),root); erase(Key_value); pre[Key_value] = 0; Key_value = 0; push_up(ch[root][1]); push_up(root);}//将从第pos个数开始的连续的tot个数修改为cvoid Make_Same(int pos,int tot,int c){ Splay(Get_kth(root,pos),0); Splay(Get_kth(root,pos+tot+1),root); Update_Same(Key_value,c); push_up(ch[root][1]); push_up(root);}//将第pos个数开始的连续tot个数进行反转void Reverse(int pos,int tot){ Splay(Get_kth(root,pos),0); Splay(Get_kth(root,pos+tot+1),root); Update_Rev(Key_value); push_up(ch[root][1]); push_up(root);}//得到第pos个数开始的tot个数的和int Get_Sum(int pos,int tot){ Splay(Get_kth(root,pos),0); Splay(Get_kth(root,pos+tot+1),root); return sum[Key_value];}//得到第pos个数开始的tot个数中最大的子段和int Get_MaxSum(int pos,int tot){ Splay(Get_kth(root,pos),0); Splay(Get_kth(root,pos+tot+1),root); return mx[Key_value];}void InOrder(int r){ if(!r)return; push_down(r); InOrder(ch[r][0]); printf("%d ",key[r]); InOrder(ch[r][1]);}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(scanf("%d%d",&n,&q) == 2) { Init(); char op[20]; int x,y,z; while(q--) { scanf("%s",op); if(strcmp(op,"INSERT") == 0) { scanf("%d%d",&x,&y); Insert(x,y); } else if(strcmp(op,"DELETE") == 0) { scanf("%d%d",&x,&y); Delete(x,y); } else if(strcmp(op,"MAKE-SAME") == 0) { scanf("%d%d%d",&x,&y,&z); Make_Same(x,y,z); } else if(strcmp(op,"REVERSE") == 0) { scanf("%d%d",&x,&y); Reverse(x,y); } else if(strcmp(op,"GET-SUM") == 0) { scanf("%d%d",&x,&y); printf("%d\n",Get_Sum(x,y)); } else if(strcmp(op,"MAX-SUM") == 0) printf("%d\n",Get_MaxSum(1,size[root]-2)); } } return 0;}
阅读全文
1 0
- 邝斌的ACM模板(伸展树(splay tree))
- 伸展树( splay tree)
- Splay Tree(伸展树)
- 伸展树(splay tree)
- 伸展树(Splay Tree)
- 伸展树(Splay tree)
- Splay tree 伸展树 (不含区间操作)模板
- 【模板篇】伸展树Splay Tree(此坑待填)
- 树学习 ---------伸展树(splay Tree)
- 伸展树(Splay tree)学习小结
- 伸展树(Splay Tree)尽收眼底
- 伸展树(Splay Tree)尽收眼底
- splay tree(伸展树)详解
- 伸展树(Splay tree)学习小结
- 05. 伸展树(Splay Tree)
- 伸展树模板小结(Splay Tree)
- 伸展树(splay)
- 伸展树(Splay)
- 欢迎使用CSDN-markdown编辑器
- Python中的语句
- 编程语言的原子性与可见性
- Spring MVC 解读——<mvc:annotation-driven/>
- *leetcode 30 findSubstring
- 邝斌的ACM模板(伸展树(splay tree))
- MATLAB中读取网络照片
- PAT 1043. Is It a Binary Search Tree
- 京东和亚马逊商品页面的爬取
- 使用MATLAB模糊数据工具箱和simulink实现单交叉路口交通灯实时配时算法(二)
- 前端调用PHP函数的方式
- Codeforces Round #432 (Div. 2) C Five Dimensional Points
- 配置matlab背景色与字体
- Hibernate复合主键的使用