首页 > 代码库 > BZOJ 1588 营业额统计 Splay
BZOJ 1588 营业额统计 Splay
主要操作为Splay中插入节点,查找前驱和后继节点。
1: #include <cstdio>
2: #include <iostream>
3: #include <cmath>
4: using namespace std;
5: #define MaxL 100005
6: #define INF 0x7ffffff
7: #define keyTree sp[sp[root].child[1]].child[0]
8:
9: struct SplayTreeNode
10: {
11: int parent, child[2]; // parent and child[0] left child[1] right
12: int sz, val; // sz 表示当前节点为根的子树总节点个数. val表示当前节点的键值。
13: int lazy; // 延迟标记
14: long long sum; // 以x为根节点的子树的所有的和
15: };
16:
17: int num[MaxL];
18: struct SpalyTree
19: {
20: SplayTreeNode sp[MaxL]; // save space
21: int gc[MaxL]; // Garbage Collection idx
22: int root; // root idx
23: int idx; // Forward allocate tree
24: int idxrev; // garbage allocated nodes used for next allocation priority
25:
26: /*
27: A B
28: / \ R(B,RR)-> / \
29: B C <-R(A,LL) D A
30: / \ / \
31: D E E C
32: */
33: void Rotate(int x,int f) // f ==0 l rot,1 r rot
34: {
35: int y = sp[x].parent;
36: PushDown(y);
37: PushDown(x);
38: sp[y].child[!f] = sp[x].child[f];
39: sp[sp[x].child[f]].parent = y;
40: sp[x].parent = sp[y].parent;
41: if(sp[x].parent)
42: sp[sp[y].parent].child[ sp[sp[y].parent].child[1] == y]= x;
43: sp[x].child[f] = y;
44: sp[y].parent = x;
45: PushUp(y);
46: }
47:
48: // x to be the child of goal, x and goal are key
49: void Splay(int x, int goal)
50: {
51: PushDown(x);
52: while(sp[x].parent != goal)
53: {
54: if(sp[sp[x].parent].parent == goal)
55: Rotate(x, sp[sp[x].parent].child[0] == x);
56: else
57: {
58: int y = sp[x].parent, z = sp[y].parent;
59: int f = sp[z].child[0] == y;
60: if(sp[y].child[f] == x)
61: Rotate(x,!f), Rotate(x,f);
62: else
63: Rotate(y,f), Rotate(x,f);
64: }
65: }
66: PushUp(x);
67: if(goal == 0) root = x;
68: }
69:
70: // 把第k个的数转到goal下边,一般用来调整区间, 返回其key 键
71: int RotateTo(int k, int goal)
72: {
73: int x = root;
74: PushDown(x);
75: while(sp[sp[x].child[0]].sz !=k)
76: {
77: if( k< sp [ sp[x].child[0] ].sz)
78: x = sp[x].child[0];
79: else
80: {
81: k -= sp[sp[x].child[0]].sz +1;
82: x = sp[x].child[1];
83: }
84: PushDown(x);
85: }
86: cout<<"Rotate "<<x<<" goal "<<goal<<endl;
87: Splay(x, goal);
88: return x;
89: }
90:
91: // insert a value, return the key
92: // first find the key, then insert a value.
93: // 不重复插入
94: pair<int,bool> Insert(int val)
95: {
96: int p = root;
97: while( sp[p].val == val || sp[p].child[ sp[p].val < val ])
98: {
99: if(sp[p].val == val)
100: {
101: Splay(p, 0);
102: return make_pair(p,false);
103: }
104: p = sp[p].child[sp[p].val < val];
105: }
106: int x = NewNode(sp[p].child[sp[p].val < val], val);
107: sp[x].parent = p;
108: Splay(x, 0);
109: return make_pair(x, true);
110: }
111:
112: int findPrefix(int x)
113: {
114: Splay(x,0);
115: int p = sp[x].child[0];
116: if(p)
117: {
118: while(sp[p].child[1])
119: p = sp[p].child[1];
120: }
121: return p;
122: }
123:
124: int findSuffix(int x)
125: {
126: Splay(x, 0);
127: int p = sp[x].child[1];
128: if(p)
129: {
130: while(sp[p].child[0])
131: p = sp[p].child[0];
132: }
133: return p;
134: }
135:
136:
137: int NewNode(int &x, int c)
138: {
139: if( idxrev) x = gc[--idxrev];
140: else x = ++idx;
141: sp[x].child[1] = 0, sp[x].child[0] = 0, sp[x].parent = 0;
142: sp[x].sz = 1;
143: sp[x].val = sp[x].sum = c;
144: sp[x].lazy = 0;
145: return x;
146: }
147:
148: //把以x为祖先结点(x 也算)删掉放进内存池,回收内存
149: void eraseSubTree(int x)
150: {
151: int father = sp[x].parent;
152: int head = idxrev , tail = idxrev;
153: for (gc[tail++] = x ; head < tail ; head ++)
154: {
155: idxrev++;
156: if( sp[gc[head]].child[0]) gc[tail++] = sp[gc[head]].child[0];
157: if( sp[gc[head]].child[1]) gc[tail++] = sp[gc[head]].child[1];
158: }
159: sp[father].child[ sp[father].child[1] == x] = 0;
160: PushUp(father);
161: }
162:
163: void makeTree(int &x, int l, int r, int parent)
164: {
165: if(l > r) return ;
166: int m = (l+r)>>1;
167: NewNode(x,num[m]);
168: makeTree(sp[x].child[0], l, m-1, x);
169: makeTree(sp[x].child[1], m+1, r, x);
170: sp[x].parent = parent;
171: PushUp(x);
172: }
173: void Init(int n)
174: {
175: idx = idxrev = 0;
176: root = 0;
177: sp[0].child[0] = sp[0].child[1] = sp[0].parent = 0;
178: sp[0].sz = sp[0].lazy = sp[0].sum = 0;
179: }
180:
181: void Travel(int x)
182: {
183: if(x)
184: {
185: Travel( sp[x].child[0]);
186: printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x, sp[x].child[0],sp[x].child[1],sp[x].parent,sp[x].sz,sp[x].val);
187: Travel( sp[x].child[1]);
188: }
189: }
190:
191: //Problem Specific Function
192: void PushUp(int x )
193: {
194: sp[x].sz = 1 + sp[sp[x].child[0]].sz + sp[sp[x].child[1]].sz;
195: sp[x].sum = sp[x].lazy + sp[x].val + sp[sp[x].child[0]].sum + sp[sp[x].child[1]].sum;
196: }
197:
198: void PushDown(int x)
199: {
200: if(sp[x].lazy)
201: {
202: sp[x].val += sp[x].lazy;
203: sp[sp[x].child[0]].lazy += sp[x].lazy;
204: sp[sp[x].child[1]].lazy += sp[x].lazy;
205: sp[sp[x].child[0]].sum += (long long) sp[ sp[x].child[0]].sz * sp[x].lazy;
206: sp[sp[x].child[1]].sum += (long long) sp[ sp[x].child[1]].sz * sp[x].lazy;
207: sp[x].lazy = 0;
208: }
209: }
210:
211: void update(int l, int r, int c )
212: {
213: RotateTo(l-1,0);
214: RotateTo(r+1,root);
215: sp[keyTree].lazy += c;
216: sp[keyTree].sum += (long long) c * sp[keyTree].sz;
217: }
218:
219: // query for the interval [l,r]
220: void query(int l, int r)
221: {
222: RotateTo(l-1,0);
223: RotateTo(r+1,root);
224: // int keyTree = sp [sp[root].child[1] ].child[0];
225: printf("%lld\n",sp[keyTree].sum);
226: }
227: } spt;
228:
229: int abs(int x)
230: {
231: if(x < 0) return -x;
232: else return x;
233: }
234: int main()
235: {
236:
237: //freopen("1.txt","r",stdin);
238: int n,m;
239: cin>>n;
240: m = 0;
241: for(int i=0; i<n; i++)
242: scanf("%d",&num[i]);
243: spt.Init(0);
244: int ret = 0;
245: while(m!=n)
246: {
247: pair<int,bool> state = spt.Insert(num[m]);
248: if(state.second != 0)
249: {
250: int pre = spt.findPrefix(state.first);
251: int nxt = spt.findSuffix(state.first);
252: int ans = INF;
253: if(pre)
254: ans = abs(num[m] - spt.sp[pre].val);
255: if(nxt)
256: {
257: int x = abs(num[m] - spt.sp[nxt].val);
258: ans = std::min(ans, x );
259: }
260:
261: if(pre == 0 && nxt == 0) ans = num[0];
262: // cout<<num[m]<<" "<<pre<<" "<<nxt<<" "<<ans<<endl;
263: ret += ans;
264: }
265: m++;
266: }
267: cout<<ret<<endl;;
268: return 0;
269: }
270:
271:
272:
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。