SPOJ 4487 Splay 基本操作
插入操作,删除操作和置换操作都是单点的,所以不需要lazy标记。这个很简单,都是两次RotateTo,一次Splay操作就搞定。
求最大连续字段和的操作和线段树的题目类似,只需要保存最左边的连续最大字段和,最右边的连续最大字段和,整个子树的连续最大字段和就OK,整个子树的和就OK。
注意PushUp函数的写法就OK
//Problem Specific Function
void PushUp(int x )
{
int ll = sp[x].child[0], rr = sp[x].child[1];
// sz, lsum , rsum , msum, sum
sp[x].sz = 1 + sp[sp[x].child[0]].sz + sp[sp[x].child[1]].sz;
sp[x].sum = sp[x].val + sp[sp[x].child[0]].sum + sp[sp[x].child[1]].sum;
sp[x].lsum = max(sp[ll].lsum, sp[ll].sum + sp[x].val + max(sp[rr].lsum, 0));
sp[x].rsum = max(sp[rr].rsum, sp[rr].sum + sp[x].val + max(sp[ll].rsum , 0));
// 这里类似于线段树的
sp[x].msum = max(max(sp[ll].msum, sp[rr].msum), sp[x].val + max(sp[ll].rsum, 0) + max(sp[rr].lsum, 0));
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
这个题目的代码
1:
2: #include <cstdio>
3: #include <iostream>
4:
5: using namespace std;
6: #define INF 10009
7: #define MaxL 222222
8: #define keyTree sp[sp[root].child[1]].child[0]
9:
10: struct SplayTreeNode
11: {
12: int parent, child[2]; // parent and child[0] left child[1] right
13: int sz, val; // sz 表示当前节点为根的子树总节点个数. val表示当前节点的键值。
14: int sum; // 以x为根节点的子树的所有的和
15: int lsum; // 以该点为根的子树的左子树最大的连续和 [left, x)
16: int rsum; // 以该点为根的子树的右子树 最大的连续和 (x, right]
17: int msum; // 以该点为根的子树中的连续最大字段和
18: };
19:
20: int num[MaxL];
21: struct SpalyTree
22: {
23: SplayTreeNode sp[MaxL]; // save space
24: int gc[MaxL]; // Garbage Collection idx
25: int root; // root idx
26: int idx; // Forward allocate tree
27: int idxrev; // garbage allocated nodes used for next allocation priority
28:
29: /*
30: A B
31: / \ R(B,RR)-> / \
32: B C <-R(A,LL) D A
33: / \ / \
34: D E E C
35: */
36: void Rotate(int x,int f) // f ==0 l rot,1 r rot
37: {
38: int y = sp[x].parent;
39: //PushDown(y);
40: //PushDown(x);
41: sp[y].child[!f] = sp[x].child[f];
42: sp[sp[x].child[f]].parent = y;
43: sp[x].parent = sp[y].parent;
44: if(sp[x].parent)
45: sp[sp[y].parent].child[ sp[sp[y].parent].child[1] == y]= x;
46: sp[x].child[f] = y;
47: sp[y].parent = x;
48: PushUp(y);
49: }
50:
51: void Splay(int x, int goal)
52: {
53: //PushDown(x);
54: while(sp[x].parent != goal)
55: {
56: if(sp[sp[x].parent].parent == goal)
57: Rotate(x, sp[sp[x].parent].child[0] == x);
58: else
59: {
60: int y = sp[x].parent, z = sp[y].parent;
61: int f = sp[z].child[0] == y;
62: if(sp[y].child[f] == x)
63: Rotate(x,!f), Rotate(x,f);
64: else
65: Rotate(y,f), Rotate(x,f);
66:
67: }
68: }
69: PushUp(x);
70: if(goal == 0) root = x;
71: }
72: // 把第k个的数转到goal下边,一般用来调整区间
73: int RotateTo(int k, int goal)
74: {
75: int x = root;
76: //PushDown(x);
77: while(sp[sp[x].child[0]].sz !=k)
78: {
79: if( k< sp [ sp[x].child[0] ].sz)
80: x = sp[x].child[0];
81: else
82: {
83: k -= sp[sp[x].child[0]].sz +1;
84: x = sp[x].child[1];
85: }
86: // PushDown(x);
87: }
88: // cout<<"Rotate "<<x<<" goal "<<goal<<endl;
89: Splay(x, goal);
90: return x;
91: }
92:
93: void NewNode(int &x, int c)
94: {
95: if( idxrev) x = gc[--idxrev];
96: else x = ++idx;
97: sp[x].child[1] = 0, sp[x].child[0] = 0, sp[x].parent = 0;
98: sp[x].sz = 1;
99: sp[x].val = sp[x].sum = sp[x].lsum = sp[x].rsum = sp[x].msum = c;
100: //sp[x].lazy = 0;
101: }
102:
103: //把以x为祖先结点(x 也算)删掉放进内存池,回收内存
104: void eraseSubTree(int x)
105: {
106: int father = sp[x].parent;
107: int head = idxrev , tail = idxrev;
108: for (gc[tail++] = x ; head < tail ; head ++)
109: {
110: idxrev++;
111: if( sp[gc[head]].child[0]) gc[tail++] = sp[gc[head]].child[0];
112: if( sp[gc[head]].child[1]) gc[tail++] = sp[gc[head]].child[1];
113: }
114: sp[father].child[ sp[father].child[1] == x] = 0;
115: PushUp(father);
116: }
117:
118:
119: void makeTree(int &x, int l, int r, int parent)
120: {
121: if(l > r) return ;
122: int m = (l+r)>>1;
123: NewNode(x,num[m]);
124: makeTree(sp[x].child[0], l, m-1, x);
125: makeTree(sp[x].child[1], m+1, r, x);
126: sp[x].parent = parent;
127: PushUp(x);
128: }
129: void Init(int n)
130: {
131: idx = idxrev = 0;
132: root = 0;
133: sp[0].child[0] = sp[0].child[1] = sp[0].parent = 0;
134: sp[0].sz = sp[0].sum = 0;
135: sp[0].val = sp[0].lsum = sp[0].rsum = sp[0].msum = -INF;
136: NewNode(root, -INF);
137: NewNode(sp[root].child[1], -INF);
138: sp[idx].parent = root;
139: sp[root].sz = 2;
140: makeTree( sp [sp[root].child[1] ].child[0] , 1, n, sp[root].child[1]);
141: PushUp(sp[root].child[1]);
142: PushUp(root);
143: }
144:
145: void Travel(int x)
146: {
147: if(x)
148: {
149: Travel( sp[x].child[0]);
150: printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d sum = %2d\n",x, sp[x].child[0],sp[x].child[1],sp[x].parent,sp[x].sz,sp[x].val, sp[x].sum);
151: Travel( sp[x].child[1]);
152: }
153: }
154:
155: //Problem Specific Function
156: void PushUp(int x )
157: {
158: int ll = sp[x].child[0], rr = sp[x].child[1];
159: // sz, lsum , rsum , msum, sum
160: sp[x].sz = 1 + sp[sp[x].child[0]].sz + sp[sp[x].child[1]].sz;
161: sp[x].sum = sp[x].val + sp[sp[x].child[0]].sum + sp[sp[x].child[1]].sum;
162: sp[x].lsum = max(sp[ll].lsum, sp[ll].sum + sp[x].val + max(sp[rr].lsum, 0));
163: sp[x].rsum = max(sp[rr].rsum, sp[rr].sum + sp[x].val + max(sp[ll].rsum , 0));
164: // 这里类似于线段树的
165: sp[x].msum = max(max(sp[ll].msum, sp[rr].msum), sp[x].val + max(sp[ll].rsum, 0) + max(sp[rr].lsum, 0));
166: }
167:
168: void Insert(int pos, int m)
169: {
170: RotateTo(pos - 1, 0);
171: RotateTo(pos, root);
172: int p = 0;
173: NewNode(p, m);
174: keyTree = p;
175: sp[p].parent = sp[root].child[1];
176: Splay(p,0);
177: }
178:
179: void Delete(int pos)
180: {
181: RotateTo(pos-1, 0);
182: RotateTo(pos+1, root);
183: eraseSubTree(keyTree);
184: Splay(sp[root].child[1], 0);
185: }
186:
187: void Replace(int pos, int m)
188: {
189: RotateTo(pos-1, 0);
190: RotateTo(pos+1, root);
191: int x = keyTree;
192: sp[x].val = sp[x].sum = sp[x].lsum = sp[x].rsum = sp[x].msum = m;
193: Splay(keyTree,0);
194: }
195:
196: int Query(int l, int r)
197: {
198: RotateTo(l -1, 0);
199: RotateTo(r+1, root);
200:
201: int ret = sp[keyTree].msum;
202: Splay(keyTree,0);
203: return ret;
204: }
205: } spt;
206:
207:
208: int main()
209: {
210: // freopen("1.txt","r",stdin);
211: int n;
212: while(scanf("%d",&n)!=EOF)
213: {
214: for(int i=1; i<=n; i++)
215: scanf("%d",&num[i]);
216: spt.Init(n);
217: int q;
218: scanf("%d", &q);
219: while(q--)
220: {
221: char op[2];
222: scanf("%s",op);
223: int pos,m;
224: if(op[0]=='I')
225: {
226: n++;
227: scanf("%d%d",&pos, &m);
228: spt.Insert(pos,m);
229: }
230: else if(op[0]=='D')
231: {
232: n--;
233: // scanf_(pos);
234: scanf("%d", & pos);
235: spt.Delete(pos);
236: }
237: else if(op[0]=='R')
238: {
239: scanf("%d%d",&pos, &m);
240: spt.Replace(pos,m);
241: }
242: else if(op[0]=='Q')
243: {
244: scanf("%d%d", &pos, &m);
245: printf("%d\n", spt.Query(pos,m));
246: }
247: }
248: }
249: return 0;
250: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
SPOJ 4487 Splay 基本操作的更多相关文章
- spoj 4487. Can you answer these queries VI (gss6) splay 常数优化
4487. Can you answer these queries VI Problem code: GSS6 Given a sequence A of N (N <= 100000) in ...
- SPOJ 4487. Can you answer these queries VI splay
题目链接:点击打开链接 题意比較明显,不赘述. 删除时能够把i-1转到根,把i+1转到根下 则i点就在 根右子树 的左子树,且仅仅有i这一个 点 #include<stdio.h> #in ...
- Splay基本操作
我们以一道题来引入吧! 传送门 题目说的很清楚,我们的数据结构要支持:插入x数,删除x数,查询数的排名和排名为x的数,求一个数前驱后继. 似乎用啥现有的数据结构都很难做到在O(nlogn)的复杂度中把 ...
- 【BZOJ-1552&3506】robotic sort&排序机械臂 Splay
1552: [Cerc2007]robotic sort Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 806 Solved: 329[Submit][ ...
- splay详解(一)
前言 Spaly是基于二叉查找树实现的, 什么是二叉查找树呢?就是一棵树呗:joy: ,但是这棵树满足性质—一个节点的左孩子一定比它小,右孩子一定比它大 比如说 这就是一棵最基本二叉查找树 对于每次插 ...
- splay:优雅的区间暴力!
万年不更的blog主更新啦!主要是最近实在忙,好不容易才从划水做题的时间中抽出一段时间来写这篇blog 首先声明:这篇blog写的肯定会很基础...因为身为一个蒟蒻深知在茫茫大海中找到一个自己完全能够 ...
- POJ3468:A Simple Problem with Integers (线段树||树状数组||Splay解决基本问题的效率对比)
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of op ...
- Splay&LCT
Splay && LCT \(\text{Splay}\) 基本操作 1.\(Zig \& Zag\) 其思想是维护中序遍历不变 实现中我们不真的用\(Zig\)或\(Zag\ ...
- 【学术篇】NOIP2017 d2t3 列队phalanx splay做法
我可去他的吧.... ==============先胡扯些什么的分割线================== 一道NOIP题我调了一晚上...(其实是因为昨晚没有找到调试的好方法来的说...) 曾经我以 ...
随机推荐
- VMware系统运维(一)安装Esxi
1.下载ISO文件,开始安装,如图1,直接按回车进行安装. 图1 2.按回车键继续安装,如图2所示 图2 3.选择要安装系统的磁盘,按回车继续,如图3所示 图3 4.选择对应的键盘语言,按回车继续,如 ...
- 基于BaseHTTPServer的简单存储服务器
服务器代码: from BaseHTTPServer import BaseHTTPRequestHandler from BaseHTTPServer import HTTPServer impor ...
- [未完成]WebService学习第一天学习笔记
[未完成]WebService学习第一天学习笔记[未完成]WebService学习第一天学习笔记
- [ImportNew]8张图理解Java
http://www.importnew.com/11725.html 1.字符串的不变性. 下面这张图展示了这段代码做了什么 String s = "abcd"; s = s.c ...
- hdu 4421 2-SAT问题
思路:我们需要判断是否有满足的a[n],其实也就是对每一个二进制位进行判断,看是否有满足的.那么我们每次取出一个二进制位,这样每一位只有0,1两种状态,就成了比较典型的2-SAT问题了. #inclu ...
- poj 1679 次小生成树
次小生成树的求法: 1.Prime法 定义一个二维数组F[i][j]表示点i到点j在最小生成树中的路径上的最大权值.有个知识就是将一条不在最小生成树中的边Edge加入最小生成树时,树中要去掉的边就是E ...
- gVim 配置方案 采用Vundle管理插件
在Linux下配置vim非常简单,尤其是采用Vundle来管理插件,使得一切用起来得心应手. Maple大神在github上公布了自己的vim配置方案,相当方便好用.详见 https://github ...
- asp.net中web.config配置节点大全详解【转】
web.config 文件查找规则: (1)如果在当前页面所在目录下存在web.config文件,查看是否存在所要查找的结点名称,如果存在返回结果并停止查找. (2)如果当前页面所在目录下不存在web ...
- css选择器有哪些?哪些属性可以继承?优先级算法如何计算?内联和important哪个优先
CSS选择器:基本可以分为通配选择器,标签选择器,类选择器,ID选择器,简单属性选择,具体属性选择,根据部分属性值选择,特定属性选择,从结构上来分还有后代选择器,子元素选择器,相邻兄弟选择器以及伪类. ...
- PB11.5创建及调用WebService
我今天做了这个“PB创建及调用WebService”的小作业,下面我来分享一下我的整个实践过程以及我遇到的问题,希望对大家有所帮助,这个小作业是分以下三部来完成的: 一.构建WebService ①创 ...