bzoj 1588 splay 模板
2016-08-02 16:03
330 查看
// 每插入一个点求它与树中的点的最小绝对值 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cstdlib> #include<string> #define maxi 0x73ffffff #define maxn 200005 #define LL long long using namespace std; struct splayTree{ //关于树的备用的 int son[maxn][2];//0为左儿子,1为右儿子 int fa[maxn];// 该节点的父亲 int rt,tot;//祖宗,节点数量 int siz[maxn];//字数大小本题不需要 inline void up(int i) { siz[i] = cnt[i]+siz[son[i][0]]+siz[son[i][1]]; } inline void Rotate(int x,int flag)//flag 0 左旋,1右旋 { int y = fa[x]; //y为x父 son[y][!flag] = son[x][flag]; fa[son[x][flag]] = y;//先处理x的儿子 fa[x] = fa[y]; if(fa[y])son[fa[y]][son[fa[y]][1]==y] = x; //再处理y的父亲 fa[y] = x; //再处理 x和y son[x][flag] = y; up(y); } inline void splay(int x,int goal) //把x旋到goal后面 { while(fa[x]!=goal) { if(fa[fa[x]]==goal)Rotate(x,son[fa[x]][0]==x);//单旋 else{ int fax = fa[x],faxx = fa[fax]; int flag = (son[faxx][0]==fax); if(son[fax][flag]==x) //双左右或双右左旋 { Rotate(x,!flag); Rotate(x,flag); } else //左左旋右右旋 { Rotate(fax,flag); Rotate(x,flag); } } } up(x); if(goal==0)rt = x; } inline void visit(int x) //调试GG { printf("本点 %d 价值 %d 左二子 %d 右儿子 %d 祖宗 %d\n",x,va[x],son[x][0],son[x][1],rt); if(son[x][0])visit(son[x][0]); if(son[x][1])visit(son[x][1]); } //以上通用不用修改 void addNode(int val,int far) { va[++tot] = val; son[tot][0] = son[tot][1] = 0; fa[tot] = far; son[far][val>=va[far]] = tot; cnt[tot] = siz[tot] = 1; } void init() { tot = 0,rt = 1; addNode(maxi,0); addNode(-1*maxi,1); siz[1] = 2; } void inser(int pre,int far,int val)//插入啊 { if(!pre)//插入 { addNode(val,far); splay(tot,0); return ; } if(va[pre]==val) //重复计数 { cnt[pre]++; up(pre); splay(pre,0); return ; } if(val>=va[pre])inser(son[pre][1],pre,val);//继续寻找 else inser(son[pre][0],pre,val); up(pre); } void findMax(int &x,int pre,int val)//查询大于等于val的最小值 { if(!pre)return ; if(va[pre]>=val) { x = va[pre]; findMax(x,son[pre][0],val); } else findMax(x,son[pre][1],val); } void findMin(int &x,int pre,int val)//查询小于val的最大值 { if(!pre)return ; if(va[pre]<val) { x = va[pre]; findMin(x,son[pre][1],val); } else findMin(x,son[pre][0],val); } int va[maxn],cnt[maxn];//va价值 cnt统计这个点的值有多少个 }st; int main() { int n,a; int ans = 0; st.init(); scanf("%d",&n); scanf("%d",&a); st.inser(st.rt,0,a); n--; ans = a; while(n--) { int pre = 0,pre2; scanf("%d",&a); st.findMax(pre,st.rt,a); pre2 = abs(a-pre); st.findMin(pre,st.rt,a); pre2 = min(pre2,abs(a-pre)); ans+=pre2; st.inser(st.rt,0,a); } printf("%d\n",ans); return 0; }
相关文章推荐
- c++抽象类、纯虚函数以及巧用纯虚析构函数实现接口类【转】
- 求指教!!!
- Oracle PL/SQL语法格式
- 《如何阅读一本书》感后读
- python 学习(十四)之元组
- 第31条:用实例域代替序数
- spring @Value 设置默认值
- 神经网络读书笔记:《神经网络与机器学习/Simon Haykin》导言概念总结
- JQuery各种点击事件的区别
- LeetCode 62 Unique Paths
- 关于Bootstrap(二)
- C#读取系统安装的字体的方法
- POJ Problem 1383 Labyrinth【树的直径】
- mysql远程登录及修改用户密码
- Python 爬虫-爬取阿里旅行特价机票信息(2)
- [置顶] android note
- 纯虚函数与纯虚类
- 解决git 提交代码时提示空间不足:error: unpack failed: error No space left on device
- java字符串操作
- [原创]java WEB学习笔记54:Struts2学习之路--- 编写Struts2 的第一个程序,HelloWord,简述 package ,action,result