插入操作,删除操作和置换操作都是单点的,所以不需要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 基本操作,布布扣,bubuko.com