loj10143. 「一本通 4.6 例 1」营业额统计

Posted junk-yao-blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj10143. 「一本通 4.6 例 1」营业额统计相关的知识,希望对你有一定的参考价值。

思路:

  使用treap在线存数据,每次取出新读入数据的前驱与后继,与该数据差值较小的就是。(注意若已有同一个数据,特判ans+=0)

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
const int maxn = 100010;
inline void qread(int &x) {
    x = 0;
    register int ch = getchar(), flag = 0;
    while(ch < 0 || ch > 9)        {
        if(ch == -)    flag = 1;
        ch = getchar();
    }
    while(ch >= 0 && ch <= 9)    x = 10 * x + ch - 48, ch = getchar();
    if(flag)    x = -x;
}
int rt = 0, tpn, v[maxn], l[maxn], r[maxn], R[maxn], sz[maxn], vn[maxn];
inline void update(int x) {
    sz[x] = sz[l[x]] + sz[r[x]] + vn[x];
}
inline void zig(int &x) {
    int t = l[x];
    l[x] = r[t];
    r[t] = x;
    update(x);
    update(t);
    x = t;
}
inline void zag(int &x) {
    int t = r[x];
    r[x] = l[t];
    l[t] = x;
    update(x);
    update(t);
    x = t;
}
void insert(int &x, int w) {
    if(!x)    {
        x = ++tpn;
        v[x] = w;
        R[x] = rand();
        sz[x] = vn[x] = 1;
        return ;
    }
    if(w < v[x])    insert(l[x], w);
    else if(w > v[x])    insert(r[x], w);
    else            vn[x]++;
    update(x);
    if(l[x] && R[l[x]] < R[x])    zig(x);
    if(r[x] && R[r[x]] < R[x])    zag(x);
}
void pop(int &x, int w) {
    if(w < v[x])    pop(l[x], w);
    else if(w > v[x])    pop(r[x], w);
    else {
        if(vn[x] > 1)    vn[x]--;
        else if(!l[x] || !r[x])    x = l[x] | r[x];
        else if(R[l[x]] < R[r[x]])    zig(x), pop(x, w);
        else                        zag(x), pop(x, w);
    }
    update(x);
}
int ask(int x, int w){
    if(!x)        return -1;
    if(w < v[x])    return ask(l[x], w);
    if(w > v[x])    return ask(r[x], w);
    return     x;
}
int findk(int x, int k){
    if(k >= sz[l[x]] + 1 && k <= sz[l[x]] + vn[x])    return v[x];
    if(k <= sz[l[x]])    return findk(l[x], k);
    return     findk(r[x], k - sz[x] - vn[x]);
}
int findpre(int x, int w){
    int res = -0x3f3f3f3f;
    while(x){
        if(w <= v[x])    x = l[x];
        else            res = v[x], x = r[x];
    }
    return res;
}
int findnxt(int x, int w){
    int res = 0x3f3f3f3f;
    while(x){
        if(w < v[x])    res = v[x], x = l[x];
        else            x = r[x];
    }
    return res;
}
int main(void) {
    srand(11535);
    int n, ans;
    qread(n);
    qread(ans);
    insert(rt, ans);
    for(int i=2; i<=n; ++i){
        int x;
        qread(x);
        int l = findpre(rt, x), r = findnxt(rt, x);    
        if(ask(rt, x) != -1)    {insert(rt, x); continue;}
        insert(rt, x);
        ans += min(x - l, r - x);
    }    
    printf("%d
", ans);
}

 

以上是关于loj10143. 「一本通 4.6 例 1」营业额统计的主要内容,如果未能解决你的问题,请参考以下文章

loj10145. 「一本通 4.6 练习 2」郁闷的出纳员

loj10147. 「一本通 5.1 例 1」石子合并

loj10043. 「一本通 2.2 例 1」剪花布条

loj10193. 「一本通 6.1 例 1」序列的第 k 个数

loj10164. 「一本通 5.3 例 2」数字游戏

loj10165. 「一本通 5.3 例 3」Windy 数