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 ...
随机推荐
- Linux命令行下cp,rm,mv命令的使用
以下的内容来源于<鸟哥的私房菜> Linux命令行下的复制.删除与移动:cp,rm,mv cp(copy)复制 cp这个命令的用途很多,除了单纯的复制之外,还可以创建链接文件 ...
- ubuntu14_pip 安装
1:install pip python-dev sudo apt-get install python-dev sudo apt-get install libevent-dev ...
- 关于Excle中的VLookUp的函数的使用
VLookUp函数的使用,VLookUp中的V是垂直的(vertical)意思,此外与此相类似的函数还有HLOOKUP(Horizonal水平的)意思. 下面主要谈谈VLookUp的使用方法. VLo ...
- 【组合数的唯一分解定理】Uva1635
给出n.m,求得最终求和数列an=C(n-1,0)*x1 + C(n-1,1)*x2+...+C(n-1,n-1)*xn; 若xi与m无关,则an除以m的余数与xi无关,即余数不含xi的项: 输入:n ...
- 通过使用精简客户端,且不需要安装的客户端,配合PLSQL连接oracle数据库
通过使用精简客户端,且不需要安装的客户端,配合PLSQL连接oracle数据库. 首先下载安装包在Oralce官方网站上下载Oracle Instantclient Basic package.地址如 ...
- Map集合的四种遍历方式
很久以前写的代码,和上一个做比较吧!便于以后查看 import java.util.HashMap; import java.util.Iterator; import java.util.Map; ...
- asp自动解析网页中的图片地址,并将其保存到本地服务器
程序实现功能:自动将远程页面的文件中的图片下载到本地. 程序代码 <% '将本文保存为 save2local.asp '测试:save2local.asp?url=http://ent.sina ...
- HDOJ2022海选女主角
海选女主角 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- 网易新闻RSS阅读器
首先需要分析网易RSS订阅中心的网页布局情况. 网易RSS订阅中心:http://www.163.com/rss/ 你会发现RSS文件由一个<channel>元素及其子元素组成,除了频道本 ...
- CSS之鼠标经过字体光标形状的改变
CSS中的cursor属性是规定要显示的光标的类型(形状). 参阅JavaScript正则表达式 default 默认光标(通常是一个箭头) auto 默认.浏览器设置的光标. crosshair 光 ...