《算法笔记》13.2小节——专题扩展->树状数组(BIT) 问题 D: 数列-训练套题T10T3

数列(sequence.pas/c/cpp)

- 问题描述

一个简单的数列问题:给定一个长度为n的数列,求这样的三个元素ai, aj, ak的个数,满足ai < aj > ak,且i < j < k。

- 输入数据

第一行是一个整数n(n <= 50000)。

第二行n个整数ai(0 <= ai <= 32767)。

- 输出数据

一个数,满足ai < aj > ak (i < j < k)的个数。

- 样例输入

5

1 2 3 4 1

- 样例输出

6

分析:思路类似问题 A,先求出一个数左边有多少比它小,再求出一个数的右边有多少比它小。而问题 A 中已经知道了前面怎么求,那么求右边有多少比它大,可以把这个数组反过来存,问题就转化为求左边有多少比它小。

cpp 复制代码
#include<algorithm>
#include <iostream>
#include  <cstdlib>
#include  <cstring>
#include   <string>
#include   <vector>
#include   <cstdio>
#include    <queue>
#include    <stack>
#include    <ctime>
#include    <cmath>
#include      <map>
#include      <set>
#define INF 0x3fffffff
#define db1(x) cout<<#x<<"="<<(x)<<endl
#define db2(x,y) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<endl
#define db3(x,y,z) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<endl
#define db4(x,y,z,r) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<endl
#define db5(x,y,z,r,w) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<", "<<#w<<"="<<(w)<<endl
using namespace std;

#define lowbit(i) ((i)&(-i))

typedef struct node
{
    int val,pos;
}node;

long long getsum(int x,int n,int c[])
{
    long long sum=0;
    for(int i=x;i>0;i-=lowbit(i))
        sum+=c[i];
    return sum;
}

void update(int x,int v,int n,int c[])
{
    for(int i=x;i<=n;i+=lowbit(i))
        c[i]+=v;
    return;
}

bool cmp(node a,node b)
{
    return a.val<b.val;
}

int main(void)
{
    #ifdef test
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    clock_t start=clock();
    #endif //test

    int n;
    while(~scanf("%d",&n))
    {
        node num[n+5];
        int c1[n+5]={0},c2[n+5]={0},a[n+5]={0},b[n+5]={0};
        for(int i=0;i<n;++i)
            scanf("%d",&num[i].val),num[i].pos=i;
        sort(num,num+n,cmp);
        for(int i=0;i<n;++i)
        {
            if(i==0||num[i].val!=num[i-1].val)a[num[i].pos]=i+1;
            else a[num[i].pos]=a[num[i-1].pos];
        }
        for(int i=0;i<n;++i)
            b[i]=a[n-1-i];

        long long ans=0;
        long long sum1[n+5]={0},sum2[n+5]={0};
        for(int i=0;i<n;++i)
        {
            update(a[i],1,n,c1);sum1[i]=getsum(a[i]-1,n,c1);
            update(b[i],1,n,c2);sum2[n-1-i]=getsum(b[i]-1,n,c2);
        }
        for(int i=0;i<n;++i)
            ans+=sum1[i]*sum2[i];
        printf("%lld\n",ans);
    }

    #ifdef test
    clockid_t end=clock();
    double endtime=(double)(end-start)/CLOCKS_PER_SEC;
    printf("\n\n\n\n\n");
    cout<<"Total time:"<<endtime<<"s"<<endl;        //s为单位
    cout<<"Total time:"<<endtime*1000<<"ms"<<endl;    //ms为单位
    #endif //test
    return 0;
}

最后记录一下《算法笔记》书练习的 AC 代码: codeup/13.2树状数组 at master · maximusyoung007/codeup · GitHub

相关推荐
aqiu1111114 小时前
【算法日记 13】LeetCode 49. 字母异位词分组:哈希表的进阶“降维打击”
算法·leetcode·散列表
KaMeidebaby5 小时前
卡梅德生物技术快报|纳米抗体技术全套实操流程:AFB1 全合成文库淘选 + 分子对接定点突变参数手册
人工智能·python·tcp/ip·算法·机器学习
巴糖5 小时前
从做早餐理解 DAG 与拓扑排序:任务依赖图的核心逻辑
算法
2601_962851745 小时前
计算机毕业设计之基于YOLOV10的低光照目标检测算法研究与实现
大数据·算法·yolo·目标检测·信息可视化·cnn·课程设计
magicwt5 小时前
快手自动出价论文GAVE阅读笔记
算法
智者知已应修善业5 小时前
【P12159蓝桥杯数组翻转】2025-4-24
c语言·c++·经验分享·笔记·算法·蓝桥杯
小巧的砖头6 小时前
使用SVN+CruiseControl+ANT实现持续集成之一
学习·算法
人道领域6 小时前
【LeetCode刷题日记】贪心算法理论与实战:455.分发饼干最优解
java·开发语言·数据结构·算法·leetcode·贪心算法
小O的算法实验室7 小时前
2026年ACM TCH,动态救护车路径优化:结合 K-means 聚类与多目标粒子群算法两阶段策略
算法
在书中成长7 小时前
HarmonyOS 小游戏《对战五子棋》开发第8篇 - GomokuEngine核心引擎设计(三):五子连珠判定算法
算法·华为·harmonyos