大视野 1588 Splay入门
2015-09-24 19:21
204 查看
// 大视野 1588 Splay入门 // // 解题思路: // 其实也没啥好解释的.就是每次在当前序列中 // 找与x的最靠近的值(一个比他大,一个比他小)然后 // 这两者与x的差值的绝对值最小,依次累加,就是我们 // 所要求最后的答案.主要是为了学习Splay这个模板 // 感谢网上的大神<a target=_blank id="lnkBlogLogo" href="http://www.cnblogs.com/kane0526/"><img id="blogLogo" src="http://www.cnblogs.com/Skins/custom/images/logo.gif" alt="返回主页" /></a>我亦青灯杯里少年.挺好理解 // 然而我花了好几天的功夫,才能够把它默写下来.继续 // 加油吧~~~更难的还在后面呢.FIGNTING!!! #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int MAX_N = 50009; const int INF = 1e9; struct SplayTree{ int ch[MAX_N][2],val[MAX_N],pre[MAX_N]; int size; int rt; void Init(){ size = 0; NewNode(0,rt,-INF); NewNode(rt,ch[rt][1],INF); } void NewNode(int y,int &x,int v){ x = ++size; pre[x] = y; val[x] = v; ch[x][0] = ch[x][1] = 0; } void Insert(int a){ int x = rt; while(ch[x][val[x] < a]) x = ch[x][val[x] < a]; NewNode(x,ch[x][val[x]<a],a); Splay(size,0); } void Rotate(int x,int d){ // 旋转的操作还是要靠自己悟,我已经悟了差不多间歇性一个月了 d = 0表示左旋,d = 1右旋 int y = pre[x]; ch[y][d^1] = ch[x][d]; pre[ch[x][d]] = y; pre[x] = pre[y]; if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; ch[x][d] = y; pre[y] = x; } void Splay(int x,int goal){ // 将x转到goal,这里特殊在于goal是0.也就是所谓的虚的空节点 while(pre[x]!=goal){ if (pre[pre[x]] == goal){ if (ch[pre[x]][0] == x) Rotate(x,1); else Rotate(x,0); } else { int y = pre[x],z = pre[y]; if (ch[z][0] == y){ if (ch[y][0] == x){ // 左一字 Rotate(y,1); Rotate(x,1); }else{ Rotate(x,0); // 左之字 Rotate(x,1); } }else { if (ch[y][1] == x){ // 右一字 Rotate(y,0); Rotate(x,0); }else { Rotate(x,1); // 右之字 Rotate(x,0); } } } } if (goal == 0) rt = x; } inline int F_min(int a){ //最靠近a但是>=a int x = rt; int minv = INF; while(x){ if (val[x] == a) return a; if (val[x] > a) minv = min(minv,val[x]); if (val[x] > a) x = ch[x][0]; else x = ch[x][1]; } return minv; } inline int F_max(int a){ // 最靠近a但是<=a int x = rt; int maxv = -INF; while(x){ if (val[x] == a) return a; if (val[x] < a) maxv = max(maxv,val[x]); if (val[x] < a) x = ch[x][1]; else x = ch[x][0]; } return maxv; } }spt; int main(){ int n; //freopen("1.txt","r",stdin); while(scanf("%d",&n)!=EOF){ int a; spt.Init(); scanf("%d",&a); int ans = a; spt.Insert(a); while(--n){ if (scanf("%d",&a) == EOF) a = 0; // 这样写是因为数据有问题 //printf("a = %d f_max(a) = %d , f_min(a) = %d\n",a,spt.F_max(a),spt.F_min(a)); int x = min(fabs(a - spt.F_max(a)),fabs(spt.F_min(a) - a)); ans += x; // printf("%d %d\n",n,x); spt.Insert(a); } printf("%d\n",ans); } }
相关文章推荐
- POJ 1651 Multiplication PuzzleDP方法:
- Android 自定义View修炼-高仿猎豹清理大师自定义内存开口圆环比例进度View
- 对于项目编译时自动使用代码混淆的方法。
- 从浏览器地址栏里输入一个URL开始,到出现整个页面,网络上都发生了什么事?
- 常见的socket出错总结
- 字符串的匹配次数及匹配结束子串在主串中的位置
- 关于 LinkButton 放在 UpdataPanal 里面的一些问题
- 阶段总结3
- SQL扩展之T-SQL中的数据查询语言之统计计算
- 白话经典算法系列之六 快速排序 快速搞定
- 对代理的传值方式的深入理解以及使用
- nginx反向代理与负载均衡
- POJ 2955 Brackets (区间DP)
- 系统测试的方法和步骤初体验
- COM文件与EXE文件的区别与联系
- 恢复eclipse默认的背景色和字体等格式
- 笔试遇到的编程题
- 初在arm开发板测试经历
- Android利用Jsoup解析实现简单新闻客户端
- POJ 1062 昂贵的聘礼 (最短路应用 Dijkstra算法)