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:
.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; }
BZOJ 1588 营业额统计 Splay的更多相关文章
- [bzoj] 1588 营业额统计 || Splay板子题
原题 给出一个n个数的数列ai ,对于第i个元素ai定义\(fi=min(|ai-aj|) (1<=j<i)\),f1=a1,求\(/sumfi\) Splay板子题. Splay讲解:h ...
- BZOJ 1588 营业额统计
Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每 ...
- (HYSBZ)BZOJ 1588 营业额统计
营业额统计 Time Limit: 5000MS Memory Limit: 165888KB 64bit IO Format: %lld & %llu Description 营业额 ...
- BZOJ 1588 营业额统计 set
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1588 题目大意: 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交 ...
- bzoj 1588营业额统计(HNOI 2002)
http://www.lydsy.com/JudgeOnline/problem.php?id=1588 splay bottom-up的数组实现. 题意就是给你一组数,求每个数与在其前面且与其最相 ...
- Bzoj 1588: [HNOI2002]营业额统计(splay)
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MB Description 营业额统计 Tiger最近被公司升任为营业部经理,他上 ...
- 1588: [HNOI2002]营业额统计 (splay tree)
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 5783 Solved: 1859[Submit][Stat ...
- 【BZOJ-1588】营业额统计 Splay
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 12485 Solved: 4508[Submit][Sta ...
- [HNOI2002]营业额统计 Splay tree入门题
题目连接:http://www.lydsy.com/JudgeOnline/problem.php?id=1588 1588: [HNOI2002]营业额统计 Time Limit: 5 Sec ...
随机推荐
- 从医生看病和快餐店点餐理解Node.js的事件驱动
第一个例子是关于医生看病. 在美国去看医生,需要填写大量表格,比如保险.个人信息之类,传统的基于线程的系统(thread-based system),接待员叫到你,你需要在前台填写完成这些表格,你站着 ...
- 关于JDK中的集合总结(三)
泛型: jdk1.5出现的安全机制. 好处: 1,将运行时期的问题ClassCastException转到了编译时期. 2,避免了强制转换的麻烦. <>:什么时候用?当操作的引用数据类型不 ...
- 初探html5---Video + DOM(视频播放)
1:HTML5 开发环境下 lang="en" 2: <video width="320" height="240" control ...
- Java Concurrency - Semaphore 信号量
Semaphore 是一个控制访问多个共享资源的计数器. 当一个线程想要访问某个共享资源,首先,它必须获得 semaphore.如果 semaphore 的内部计数器的值大于 0,那么 semapho ...
- Git CMD - tag: Create, list, delete or verify a tag object signed with GPG
命令格式 git tag [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>] <tagname> [& ...
- NGUI的原理机制:深入剖析UIPanel,UIWidget,UIDrawCall底层原理
这是我去搜狐畅游面试时,面试官问的一个问题.问NGUI的机制原理是什么?就是这个插件是根据什么写出来的.当时没答上来,下面是我从转载过来的,可以研究研究. 之前项目中用的NGUI的版本是3.0.7 f ...
- NUI相关术语
分享一下微软资深企业架构师.应用开发专家余涛先生书中所谈到的相关术语,以便查阅,部分术语根据个人理解加入了细化内容: 1.波束形成算法(BeamformingAlgorithm) 基于现行阵列的阵列信 ...
- 【Cocos2d入门教程六】Cocos2d-x事件篇之触摸
Cocos游戏当中产生一个事件时,可以有多个对象在监听该事件,所以有优先级(Priority).优先级越高(Priority值越小),事件响应越靠前. 关系图: 新 事件分发机制:在2.x 版本事件处 ...
- 设计模式——设计模式之禅day1
单一职责 原则的定义是:应该有且仅有一个原因引起类的变更. 单一职责原则有什么好处: 类的复杂性降低,实现什么职责都有清晰明确的定义: 可读性提高,复杂性降低,那当然可读性提高了: 可维护性提高,可读 ...
- BootStrap glyphicons字体图标
本章将讲解Bootstrap glyphicons字体图标,并通过一些实例了解它的使用,字体图标是在 Web 项目中使用的图标字体.字体图标在下载的Bootstrap的fonts文件夹中 本章将讲 ...