[HNOI2002]营业额统计

OJ题号:
  BZOJ1588、洛谷3390

题目大意:
  给定一个长度为n的数列a,求$\displaystyle{\sum_{i=1}^{n}\min_{1\leq j<i}}(|a_i-a_j|)$。

思路:
  Splay。
  每次插入后将当前结点splay到根结点,然后找出左子树中最大的数和右子树中最小的数,对root.val作差取min即可。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<algorithm>
  4 inline int getint() {
  5     char ch;
  6     bool neg=false;
  7     while(!isdigit(ch=getchar())) if(ch=='-') neg=true;
  8     int x=ch^'0';
  9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 10     return neg?-x:x; 
 11 }
 12 const int inf=0x7fffffff;
 13 class SplayTree {
 14     private:
 15         struct Node {
 16             int val;
 17             Node *par,*left,*right;
 18             Node(Node *const &p,const int v) {
 19                 par=p;
 20                 val=v;
 21                 left=right=NULL;
 22             }
 23         };
 24         void rotate_left(Node *p) {
 25             Node *q=p->par;
 26             q->right=p->left;
 27             if(q->right) q->right->par=q;
 28             p->left=q;
 29             p->par=q->par;
 30             q->par=p;
 31             if(!p->par) {
 32                 root=p;
 33             } else {
 34                 if(q==p->par->left) {
 35                     p->par->left=p;
 36                 } else {
 37                     p->par->right=p;
 38                 }
 39             }
 40         }
 41         void rotate_right(Node *p) {
 42             Node *q=p->par;
 43             q->left=p->right;
 44             if(q->left) q->left->par=q;
 45             p->right=q;
 46             p->par=q->par;
 47             q->par=p;
 48             if(!p->par) {
 49                 root=p;
 50             } else {
 51                 if(q==p->par->left) {
 52                     p->par->left=p;
 53                 } else {
 54                     p->par->right=p;
 55                 }
 56             }
 57         }
 58         void splay(Node *&p) {
 59             if(!p->par) return;
 60             if(p==p->par->left) {
 61                 rotate_right(p);
 62             } else {
 63                 rotate_left(p); 
 64             }
 65         }
 66         int find_left(Node *const &p) {
 67             if(!p) return inf;
 68             int t=find_left(p->left);
 69             return t!=inf?t:p->val;
 70         }
 71         int find_right(Node *const &p) {
 72             if(!p) return inf;
 73             int t=find_right(p->right);
 74             return t!=inf?t:p->val;
 75         }
 76     public:
 77         Node *root;
 78         void insert(Node *&p,Node *const &par,const int &v) {
 79             if(!p) {
 80                 p=new Node(par,v);
 81                 splay(p);
 82                 return;
 83             }
 84             if(v<=p->val) {
 85                 insert(p->left,p,v);
 86             } else {
 87                 insert(p->right,p,v);
 88             }
 89             splay(p);
 90         }
 91         int query() {
 92             int ret=inf;
 93             if(root->left) {
 94                 ret=std::min(ret,root->val-find_right(root->left));
 95             }
 96             if(root->right) {
 97                 ret=std::min(ret,find_left(root->right)-root->val);
 98             }
 99             return ret;
100         }
101 };
102 SplayTree t;
103 int main() {
104     int n=getint(),ans=0;
105     for(int i=1;i<=n;i++) {
106         int x=getint();
107         t.insert(t.root,NULL,x);
108         ans+=i==1?x:t.query();
109     }
110     printf("%d\n",ans);
111     return 0;
112 }

 

转载于:https://www.cnblogs.com/skylee03/p/7551317.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值