zoukankan      html  css  js  c++  java
  • 洛谷P2234[营业额统计]

    戳这里看原题


    这道题目一看就是要求在每个数前面的一段前缀中的前驱和后继。

    很直白地就会想到二叉平衡树。

    对于每一天的最小波动值只需要在二叉平衡树中插入节点的时候记录前驱和后继就可以很方便地算出来了。

    所以总的来说,这道题就是一道模板题

    先贴上treap的板子吧。。


     1 //treap
     2 #include <bits/stdc++.h>
     3 
     4 using namespace std;
     5 
     6 const int N = 32768;
     7 
     8 struct treap {
     9     int fa;
    10     int s[2];
    11     int wei;
    12     int key;
    13     
    14     friend void check_print(const treap a) {
    15         printf("!%d %d %d %d %d
    ", a.fa, a.s[0], a.s[1], a.wei, a.key);
    16     }
    17 }tp[N + 1];
    18 
    19 int n;
    20 int root, tot;
    21 int ans;
    22 
    23 void rotate(int x) {
    24     int y = tp[x].fa;
    25     int z = tp[y].fa;
    26     int c = tp[y].s[1] == x;
    27     tp[x].fa = z;
    28     if(z) tp[z].s[tp[z].s[1] == y] = x;
    29     tp[tp[x].s[c ^ 1]].fa = y;
    30     tp[y].s[c] = tp[x].s[c ^ 1];
    31     tp[x].s[c ^ 1] = y;
    32     tp[y].fa = x;
    33     if(root == y) root = x;
    34 }
    35 
    36 void set_up(int k, int f, int x) {
    37     tp[k].key = x;
    38     tp[k].wei = rand();
    39     tp[k].fa = f;
    40     tp[f].s[x > tp[f].key] = k;
    41 }
    42 
    43 void up(int k) {
    44     int f = tp[k].fa;
    45     while(f && tp[f].wei > tp[k].wei) {
    46         rotate(k);
    47         f = tp[k].fa;
    48     }
    49 }
    50 
    51 int insert(int k, int x, int b, int s) {
    52     if(tp[k].key == x) return 0;
    53     if(tp[k].key > x) s = min(s, tp[k].key);
    54     if(tp[k].key < x) b = max(b, tp[k].key);
    55     if(!k || !tp[k].s[x > tp[k].key]) {
    56         set_up(++tot, k, x);
    57         up(tot);
    58         if(!k) root = tot;
    59         return min(abs(b - x), abs(s - x));
    60     }
    61     return insert(tp[k].s[tp[k].key < x], x, b, s);
    62 }
    63 
    64 int main() {
    65     srand(time(NULL));
    66     int a;
    67     scanf("%d%d", &n, &a);
    68     ans += a;
    69     insert(root, a, -2e9, 2e9);
    70     for(int i = 1; i < n; i++) {
    71         scanf("%d", &a);
    72         ans += insert(root, a, -2e9, 2e9);
    73     }
    74     printf("%d
    ", ans);
    75     return 0;
    76 }
    View Code

    但是C++的STL库中有一个神奇的东西——set。

    它完美的(带了巨大常数)实现了高难度的红黑树。

    既然有这样的好东西,为何不用呢?


     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int N = 100000;
     6 
     7 int n;
     8 int a;
     9 int ans;
    10 set<int>s;
    11 
    12 int main() {
    13     scanf("%d", &n);
    14     scanf("%d", &a);
    15     s.insert(2e9);
    16     s.insert(-2e9);
    17     s.insert(2e9 + 1);
    18     s.insert(-2e9 - 1);
    19     s.insert(a);
    20     ans += a;
    21     for(int i = 1; i < n; i++) {
    22         int k1 = 1e9, k2 = 1e9, k3 = 1e9, a;
    23         scanf("%d", &a);
    24         set<int>::iterator it = s.upper_bound(a);
    25         k1 = abs(a - *it);
    26         k2 = abs(a - *it), it--;
    27         k3 = abs(a - *it), it++;
    28         ans += min(k1, min(k2, k3));
    29         s.insert(a);
    30     }
    31     printf("%d
    ", ans);
    32     return 0;
    33 }
    View Code

    至于set的用法,这里给大家推荐一个个人认为归纳的比较好的博客,可以去借鉴一下。

    戳这里

  • 相关阅读:
    Python面向对象(组合、菱形继承、多态)
    Python面向对象
    Python hash、xml、configparser、sheve、shutil模块讲解 以及 面向对象初识
    python正则re模块
    Python序列化、date、random、os模块
    Python包和日志模块
    python面向对象、模块讲解
    python递归函数、二分法、匿名函数、(sorted、map、filter内置函数应用)
    Python生成器、三元表达式、列表生成式、字典生成式、生成器表达式
    Python迭代器
  • 原文地址:https://www.cnblogs.com/aha--CYJ/p/8395196.html
Copyright © 2011-2022 走看看