题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1588
题目描述: 给你N个数, 定义f(i) 为第i个数与i个数绝对值的最小值, 求f(1) + f(2) + f(3) + ....... + f(n)
解题思路: 如何快速的找到与插入的值差的最小值, 就是左子树的最大值与右子树的最小值的绝对值差值的较小者。 一道平衡二叉树的模板题, 自己也复习了一下数据结构
代码:
/* *********************************************** Author :Kirisame_Marisa blog :http://www.cnblogs.com/KirisameMarisa/ Created Time :2015年03月24日 星期二 20时45分12秒 File Name :splay.cpp ************************************************ */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=100010; #define eps 1e-10 #define zero(x) (fabs(x)<eps) #define REP(X,N) for(int X=0;X<N;X++) #define REP2(X,L,R) for(int X=L;X<=R;X++) #define CLR(A,X) memset(A,X,sizeof(A)) #define PB(X) push_back(X) #define MP(X,Y) make_pair(X,Y) #define IT iterator #define test puts("OK") typedef long long ll; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VII; const int null=-1; struct node { int par; int cld[2]; //0是左儿子,1是右儿子 int key; } ts[MAXN]; int root,cnt; void init() { root=null; cnt=0; } int newnode(int p,int k) { ts[cnt].key=k; ts[cnt].par=p; ts[cnt].cld[0]=ts[cnt].cld[1]=null; return cnt++; } void rotate(int x,int k) //k=0为左旋,k=1为右旋 { int y=ts[x].par; ts[y].cld[!k]=ts[x].cld[k]; if(ts[x].cld[k]!=null) ts[ts[x].cld[k]].par=y; ts[x].par=ts[y].par; if(ts[y].par!=null) { if(y==ts[ts[y].par].cld[0]) ts[ts[y].par].cld[0]=x; else ts[ts[y].par].cld[1]=x; } ts[y].par=x; ts[x].cld[k]=y; } void splay(int x,int S) //伸展操作,将x旋转到目标节点,其中S为目标节点的parent { while(ts[x].par!=S) { int p=ts[x].par; if(ts[p].par==S) rotate(x,ts[p].cld[0]==x); else { int d=(ts[ts[p].par].cld[0]==p); if(ts[p].cld[d]==x) rotate(x,!d),rotate(x,d); else rotate(p,d),rotate(x,d); } } if(S==-1) root=x; } bool insert(int x) { if(root==null) { root=newnode(null,x); return 1; } int r=root,pre=null; while(r!=null) { if(ts[r].key==x) { splay(r,null); //如果直接找到的话就不新建节点,直接splay return 0; } else { pre=r; r=ts[r].cld[ts[r].key<x]; } } int &t=ts[pre].cld[ts[pre].key<x]; t=newnode(pre,x); splay(t,null); return 1; } int getlow(int x) //获取比它小的最大值。由于插入操作x已经被旋转到根节点,所以只要寻找左子树的最大值即可,下同 { int d=ts[root].cld[0]; if(d==null) return INF; while(ts[d].cld[1]!=null) d=ts[d].cld[1]; return x-ts[d].key; } int getup(int x) //获取比它大的最小值 { int d=ts[root].cld[1]; if(d==null) return INF; while(ts[d].cld[0]!=null) d=ts[d].cld[0]; return ts[d].key-x; } void debug(int x) { int l=ts[x].cld[0],r=ts[x].cld[1]; if(l!=null) debug(l); printf("id:%2d key:%2d par:%2d lcd:%2d rcd:%2d ",x,ts[x].key,ts[x].par,l,r); if(r!=null) debug(r); } int main() { //freopen("in","r",stdin); //freopen("out","w",stdout); init(); int n,x,sum=0; scanf("%d%d",&n,&x); sum+=x; insert(x); REP(i,n-1) { x=0; scanf("%d",&x); bool temp=insert(x); if(temp) sum+=min(getlow(x),getup(x)); } printf("%d ",sum); return 0; }
思考: 模板转自http://www.cnblogs.com/KirisameMarisa/p/4366582.html, 感谢墨染之樱花......另外自己也看了看这个splay , 都是很基础的rotate和查询, 就当是回顾一下数据结构
另外有一篇讲的很好的平衡二叉树文章, 放在这里, 提醒自己时刻进行学习.......前几天发烧了, 是烧的真的严重....但是也看明白了一些事情, 学到了不少东西, 我要努力变强, 这个学校我一分钟也不想待在这里!