【Treap】BZOJ1588-[HNOI2002]营业额统计
【题目大意】
[借用别人的概括]给出一个n个数的数列a,对于第i个元素ai定义fi=min(abs(ai-aj)),(1<=j<i),其中f1=a1。输出sum(fi) (1<=i<=n)
【思路】
平衡树,易知绝对值最小的一定是前缀和后继。要注意的是由于ai和aj可能相等,即min可能等于零,要加一个判断:如果当前平衡树中的key等于要找的值,并且当前结点的cnt大于一个,则说明之前有一个值和当前相等。另外有些情况下当前要找的结点可能没有前驱或者后继,需要判断一下。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int INF=0x7fffffff; 8 struct treap 9 { 10 int key; 11 int priority; 12 treap* lson; 13 treap* rson; 14 int cnt; 15 treap() 16 { 17 key=0; 18 cnt=1; 19 /*这里初始值为1*/ 20 priority=rand(); 21 lson=rson=NULL; 22 } 23 }; 24 treap* root=NULL; 25 26 void RightRotate(treap* &rt) 27 { 28 treap* tmp=rt->lson; 29 rt->lson=tmp->rson; 30 tmp->rson=rt; 31 rt=tmp; 32 } 33 34 void LeftRotate(treap* &rt) 35 { 36 treap *tmp=rt->rson; 37 rt->rson=tmp->lson; 38 tmp->lson=rt; 39 rt=tmp; 40 } 41 42 void insert(treap* &rt,int x) 43 { 44 if (rt==NULL) 45 { 46 rt=new treap; 47 rt->key=x; 48 } 49 else 50 { 51 if (rt->key==x) 52 { 53 rt->cnt++; 54 } 55 else if (rt->key>x) 56 { 57 insert(rt->lson,x); 58 if (rt->lson->priority>rt->priority) RightRotate(rt); 59 } 60 else 61 { 62 insert(rt->rson,x); 63 if (rt->rson->priority>rt->priority) LeftRotate(rt); 64 } 65 } 66 } 67 68 int pre(treap* &rt,int x) 69 { 70 int ans=-INF; 71 treap* tmp=rt; 72 while (tmp) 73 { 74 if (tmp->key==x && tmp->cnt>1) return x; //【Attention】这句话非常重要,千万不要漏掉了! 75 if (tmp->key<x) 76 { 77 ans=max(tmp->key,ans); 78 tmp=tmp->rson; 79 } 80 else tmp=tmp->lson; 81 } 82 return ans; 83 } 84 85 int suc(treap* &rt,int x) 86 { 87 int ans=INF; 88 treap *tmp=rt; 89 while (tmp) 90 { 91 if (tmp->key>x) 92 { 93 if (tmp->key==x && tmp->cnt>1) return x; 94 ans=min(tmp->key,ans);//这里手滑写成了max(x,ans)orz 95 tmp=tmp->lson; 96 } 97 else tmp=tmp->rson; 98 } 99 return ans; 100 } 101 102 int result() 103 { 104 int n,ans; 105 if(scanf("%d",&n) == EOF) n = 0; 106 for (int i=0;i<n;i++) 107 { 108 int turnover; 109 if(scanf("%d",&turnover) == EOF) turnover = 0; 110 insert(root,turnover); 111 if (i==0) 112 { 113 ans=turnover; 114 } 115 else 116 { 117 int premax,sucmin,ad=INF; 118 premax=pre(root,turnover); 119 sucmin=suc(root,turnover); 120 if (premax!=-INF && premax!=INF) ad=min(ad,turnover-premax); 121 if (sucmin!=INF && sucmin!=-INF) ad=min(ad,sucmin-turnover); 122 if (ad!=INF && ad!=-INF) ans=ans+ad; 123 } 124 } 125 return ans; 126 } 127 128 int main() 129 { 130 printf("%d",result()); 131 return 0; 132 }