首页 > 其他分享 >abc351F Double Sum

abc351F Double Sum

时间:2024-10-08 20:13:53浏览次数:1  
标签:node cnt int Double Sum son ans data abc351F

给定数组A[N],对所有1<=i<j<=N,计算max(A[j]-A[i],0)之和。
2<=N<=4E5; 0<=A[i]<=1E8

分析:从左到后依次处理,用平衡树维护左侧A[i],对于A[j],只需要统计值小于A[j]的那些A[i]即可,可以合并求和过程转化为前缀和。

#include <bits/stdc++.h>
using i64 = long long;

template <typename TYPE>
struct SumTreap {
    struct Node {
        TYPE data, sum;
        int rnd, siz, dup, son[2];
        Node() { data = sum = rnd = siz = dup = son[0] = son[1] = 0; }
        Node(const TYPE &d, int cnt=1) { init(d, cnt); }
        void init(const TYPE & d, int cnt) {
            data = d; dup = siz = cnt; sum = d * cnt; rnd = rand(); son[0] = son[1] = 0;
        }
    };
    SumTreap(int multi=1):multiple(multi) { reset(); }
    void setmulti(int multi) { multiple = multi; }
    int newnode(const TYPE & d, int cnt) {
        if (!reuse.empty()) {
            int r = reuse.front();
            reuse.pop_front();
            node[r].init(d, cnt);
            return r;
        }
        node.push_back({d, cnt});
        return node.size() - 1;
    }
    void reset() { root = 0; node.resize(1); reuse.clear(); }
    void maintain(int x) {
        node[x].siz = node[x].dup;
        node[x].sum = node[x].data * node[x].dup;
        if (node[x].son[0]) {
            node[x].siz += node[node[x].son[0]].siz;
            node[x].sum += node[node[x].son[0]].sum;
        }
        if (node[x].son[1]) {
            node[x].siz += node[node[x].son[1]].siz;
            node[x].sum += node[node[x].son[1]].sum;
        }
    }
    void rotate(int d, int &r) {
        int k = node[r].son[d^1];
        node[r].son[d^1] = node[k].son[d];
        node[k].son[d] = r;
        maintain(r);
        maintain(k);
        r = k;
    }
    void insert(const TYPE &data, int cnt, int &r) {
        if (r) {
            if (!(data < node[r].data) && !(node[r].data < data)) {
                if (multiple) {
                    node[r].dup += cnt;
                    maintain(r);
                }
            } else {
                int d = data < node[r].data ? 0 : 1;
                int u = node[r].son[d];
                insert(data, cnt, u);
                node[r].son[d] = u;
                if (node[node[r].son[d]].rnd > node[r].rnd) {
                    rotate(d^1, r);
                } else {
                    maintain(r);
                }
            }
        } else {
            r = newnode(data, cnt);
        }
    }
    TYPE kth(int k) {
        assert(1 <= k && k <= size());
        for (int r = root; r; ) {
            int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;
            int y = node[r].dup;
            if (k <= x) {
                r = node[r].son[0];
            } else if (k <= x + y) {
                return node[r].data;
            } else {
                k -= x + y;
                r = node[r].son[1];
            }
        }
        assert(k == 0);
        return 0;
    }
    TYPE Kth(int k) {
        assert(1 <= k && k <= size());
        for (int r = root; r; ) {
            int x = node[r].son[1] ? node[node[r].son[1]].siz : 0;
            int y = node[r].dup;
            if (k <= x) {
                r = node[r].son[1];
            } else if (k <= x + y) {
                return node[r].data;
            } else {
                k -= x + y;
                r = node[r].son[0];
            }
        }
        assert(k == 0);
        return 0;
    }
    TYPE ksum(int k) {
        assert(0 <= k && k <= node[root].siz);
        TYPE ans = 0;
        for (int r = root; r && k; ) {
            int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;
            int y = node[r].dup;
            if (k <= x) {
                r = node[r].son[0];
            } else if (k <= x + y) {
                ans += node[node[r].son[0]].sum + node[r].data * (k - x);
                k = 0;
            } else {
                ans += node[node[r].son[0]].sum + node[r].data * y;
                k -= x + y;
                r = node[r].son[1];
            }
        }
        return ans;
    }
    TYPE kSum(int k) {
        assert(0 <= k && k <= node[root].siz);
        TYPE ans = 0;
        for (int r = root; r && k; ) {
            int x = node[r].son[1] ? node[node[r].son[1]].siz : 0;
            int y = node[r].dup;
            if (k <= x) {
                r = node[r].son[1];
            } else if (k <= x + y) {
                ans += node[node[r].son[1]].sum + node[r].data * (k - x);
                k = 0;
            } else {
                ans += node[node[r].son[1]].sum + node[r].data * y;
                k -= x + y;
                r = node[r].son[0];
            }
        }
        return ans;
    }
    void erase(const TYPE& data, int cnt, int & r) {
        if (r == 0) return;
        int d = -1;
        if (data < node[r].data) {
            d = 0;
        } else if (node[r].data < data) {
            d = 1;
        }
        if (d == -1) {
            node[r].dup -= cnt;
            if (node[r].dup > 0) {
                maintain(r);
            } else {
                if (node[r].son[0] == 0) {
                    reuse.push_back(r);
                    r = node[r].son[1];
                } else if (node[r].son[1] == 0) {
                    reuse.push_back(r);
                    r = node[r].son[0];
                } else {
                    int dd = node[node[r].son[0]].rnd > node[node[r].son[1]].rnd ? 1 : 0;
                    rotate(dd, r);
                    erase(data, cnt, node[r].son[dd]);
                }
            }
        } else {
            erase(data, cnt, node[r].son[d]);
        }
        if (r) maintain(r);
    }
    int ltcnt(const TYPE &data) {
        int ans = 0;
        for (int r = root; r; ) {
            int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;
            if (node[r].data < data) {
                ans += node[r].dup + x;
                r = node[r].son[1];
            } else if (data < node[r].data) {
                r = node[r].son[0];
            } else {
                ans += x;
                break;
            }
        }
        return ans;
    }
    int gtcnt(const TYPE &data) {
        int ans = 0;
        for (int r = root; r; ) {
            int x = node[r].son[1] ? node[node[r].son[1]].siz : 0;
            if (node[r].data < data) {
                r = node[r].son[1];
            } else if (data < node[r].data) {
                ans += node[r].dup + x;
                r = node[r].son[0];
            } else {
                ans += x;
                break;
            }
        }
        return ans;
    }
    int count(const TYPE &data) {
        for (int r = root; r; ) {
            if (data < node[r].data) {
                r = node[r].son[0];
            } else if (node[r].data < data) {
                r = node[r].son[1];
            } else {
                return node[r].dup;
            }
        }
        return 0;
    }
    std::pair<bool,TYPE> prev(const TYPE &data) {
        std::pair<bool,TYPE> ans = {false, 0};
        for (int r = root; r; ) {
            if (node[r].data < data) {
                if (ans.first) {
                    ans.second = std::max(ans.second, node[r].data);
                } else {
                    ans = {true, node[r].data};
                }
                r = node[r].son[1];
            } else {
                r = node[r].son[0];
            }
        }
        return ans;
    }       
    std::pair<bool,TYPE> next(const TYPE &data) {
        std::pair<bool,TYPE> ans = {false, 0};
        for (int r = root; r; ) {
            if (data < node[r].data) {
                if (ans.first) {
                    ans.second = std::min(ans.second, node[r].data);
                } else {
                    ans = {true, node[r].data};
                }
                r = node[r].son[0];
            } else {
                r = node[r].son[1];
            }
        }
        return ans;
    }
    std::vector<Node> node;
    std::deque<int> reuse;
    int root, multiple;
    void insert(const TYPE& data, int cnt=1) { insert(data, cnt, root); }
    void erase(const TYPE& data, int cnt=1) { erase(data, cnt, root); }
    int size() const { return root ? node[root].siz : 0; }
    int lecnt(const TYPE& data) { return size() - gtcnt(data, root); }
    int gecnt(const TYPE& data) { return size() - ltcnt(data, root); }
};

void solve() {
    int N;
    std::cin >> N;
    SumTreap<i64> tr;
    std::vector<int> A(N);
    for (int i = 0; i < N; i++) {
        std::cin >> A[i];
    }

    i64 ans = 0;
    for (int i = 0; i < N; i++) {
        i64 cnt1 = tr.ltcnt(A[i]);
        ans += cnt1 * A[i] - tr.ksum(cnt1);
        tr.insert(A[i]);
    }
    std::cout << ans << "\n";
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    std::cout << std::fixed << std::setprecision(10);
    int t = 1;
    // std::cin >> t;
    while (t--) solve();
    return 0;
}

标签:node,cnt,int,Double,Sum,son,ans,data,abc351F
From: https://www.cnblogs.com/chenfy27/p/18452403

相关文章

  • 112. Path Sum
    GiventherootofabinarytreeandanintegertargetSum,returntrueifthetreehasaroot-to-leafpathsuchthataddingupallthevaluesalongthepathequalstargetSum.Aleafisanodewithnochildren.Example1:Input:root=[5,4,8,11,null,13,......
  • LeetCode 209 Minimum Size Subarray Sum 题目解析和python代码
    题目:Givenanarrayofpositiveintegersnumsandapositiveintegertarget,returntheminimallengthofasubarraywhosesumisgreaterthanorequaltotarget.Ifthereisnosuchsubarray,return0instead.Example1:Input:target=7,nums=[2,3,......
  • PTA 作业一 两分钟学会JAVA语言 7-3 Java程序设计-基本程序-摄氏温度转换为华氏温度
    7-3Java程序设计-基本程序-摄氏温度转换为华氏温度分数10全屏浏览切换布局作者 万静单位 北京化工大学这是一个编程题模板。编写程序,从控制台读入double型的摄氏温度值,然后转换为华氏温度,并且显示结果。转换公式如下:华氏温度=(9/5)*摄氏温度+32。输入格式:输入摄......
  • float小,double大,我把小的数放到大的空间里面,为什么还会有精度损失?
    让我们来看这样一个例子:doublea=2.3F;System.out.println(a);输出的a为2.299999952316284不再是2.3了!明明float小,double大,我把小的数放到大的空间里面,为什么还会有“精度损失”?关键点是表示精度而非“空间”大小:浮点数的存储机制(IEEE754标准):float和......
  • ubuntu更新报错Hash Sum mismatch
    查了一圈,应该是FW的问题,/etc/apt/sources.list更换成清华的源就可以了(阿里不行):debhttps://mirrors.tuna.tsinghua.edu.cn/ubuntu/jammymainrestricteduniversemultiversedeb-srchttps://mirrors.tuna.tsinghua.edu.cn/ubuntu/jammymainrestricteduniversem......
  • 2017中国大学生程序设计竞赛 - 女生专场(SDKD 2024 Summer Training Contest K2)
    A-AutomaticJudge题意\(n\)个问题,\(m\)条记录,每条记录有题号、时间、状态,第一次\(AC\)的时候计入罚时,其他没发罚\(20\)分钟。求队伍过题数和罚时。思路模拟。代码点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvoidsolve()......
  • 题解 CF1785D - Range = √Sum
    link\(\texttt{Describe}\)构造有\(n\)个数的序列,满足以下条件:\(\foralli\in[1,n]\)并且\(1\lea_i\le10^9\)。对于任何的\(1\lei,j\len(i\nej)\),\(a_i\nea_j\)。\((\max_{i=1}^{n}a_i-\min_{i=1}^{n}a_i)^2=\sum_{i=1}^{n}a_i\)。......
  • YOLOv8改进 - 注意力篇 - 引入(A2-Nets)Double Attention Networks注意力机制
    一、本文介绍作为入门性篇章,这里介绍了A2-Nets网络注意力在YOLOv8中的使用。包含A2-Nets原理分析,A2-Nets的代码、A2-Nets的使用方法、以及添加以后的yaml文件及运行记录。二、A2-Nets原理分析A2-Nets官方论文地址:A2-Nets文章A2-Nets注意力机制(双重注意力机制):它从输入图......
  • sha256sum文件哈希值和直接哈希字符串的哈希值不一样
    例如在文件test.txt里写入test没有换行。然后sha256sumtest.txt出来的结果是f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2test.txt但是在这个网站上http://encode.chahuo.com/输入test,然后以sha256方式哈希得到的结果是9f86d081884c7d659a2......
  • 要求实现一个函数 DoubleToStr(double a,int b,char * str),将参数 a 转化为字符串 str
    sprintf函数:sprintf(str,"%.*f",b,a);:sprintf是一个格式化输出函数,类似于printf,但它将输出写入到字符串中而不是标准输出。"%.*f":#include<stdio.h>//将双精度浮点数a转换为字符串str,小数点后保留b位voidDoubleToStr(doublea,intb,char*str){  //......