当前位置: 首页 > news >正文

树状数组(3)

逆序对:

题目:

输入序列\(a_1,a_2,a_3,...,a_n\),若\(i<j\)\(a_i>a_j\),则称\(<i,j>\)是一个逆序对,请你计算出序列中逆序对的总数

输入

第一行是整数n,代表序列长度

第二行是n个数\(a_i\)

输出

逆序对总数

思路:

  1. 虚拟地维护一个频次数组freq(i),表示到目前为止i,在序列中出现的次数

    (有些书将此过程称为:把数字看作树状数组的下标)

  2. 倒序遍历离散化后的数组c[i]

    统计:当前数字所能贡献的逆序对数目sum(c[i]-1),更新:树状数组tree[i]


先不考虑离散化,看这样一个例子:

屏幕截图 2026-03-04 112002

屏幕截图 2026-03-04 112207


倒序模版:

#define lowbit(x) ((x)&(-x))
vector<int> tree(N,0),a(N,0),tmp,c;
int n,idx;
ll res;void update(int x,int d)
{while(x<=n){tree[x]+=d;x+=lowbit(x);}
}int sum(int x)
{int ans=0;while(x>0){ans+=tree[x];x-=lowbit(x);}return ans;
}int main()
{cin>>n;for(int i=1;i<=n;++i){//输入cin>>a[i];tmp.push_back(a[i]);//离散化准备}sort(tmp.begin(),tmp.end());//排序tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());//去重 利于分配编号for(int i=1;i<=n;++i){idx=lower_bound(tmp.begin(),tmp.end(),a[i])-tmp.begin()+1;c.push_back(idx);//c[i]存储映射后的数字}for(int i=n-1;i>=0;--i){//用树状数组统计逆序对res+=sum(c[i]-1);update(c[i],1);}cout<<res;return 0;
}

正序模版:

#define lowbit(x) ((x)&(-x))
int n,max_val=INT_MIN,idx;
ll res;
vector<int> a(M,0),tree(M,0),tmp,c; void update(int x,int d)
{while(x<=n){tree[x]+=d;x+=lowbit(x);}
}int sum(int x)
{int ans=0;while(x>0){ans+=tree[x];x-=lowbit(x);}return ans;
}int main()
{cin>>n;for(int i=1;i<=n;++i){cin>>a[i];tmp.push_back(a[i]);}sort(tmp.begin(),tmp.end());tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());max_val=tmp.size();for(int i=1;i<=n;++i){idx=lower_bound(tmp.begin(),tmp.end(),a[i])-tmp.begin()+1;c.push_back(idx);}for(int i=0;i<=n-1;++i){res+=sum(max_val)-sum(c[i]);//sum(c[i])得到的是序列左边有几个<=c[i]update(c[i],1);				//sum(max_val)得到的是我左边有几个数=i个}								//作差:序列左边有几个>c[i]cout<<res;return 0;
}

正序vs倒序:

倒序:从右往左扫,看右边有多少个元素比我“小”

正序:从左往右扫,看左边有多少个元素比我“大”


前缀和问题vs逆序对问题:

前缀和

  1. 原数组:a:{5,4,2,6,3,1}
  2. sum(x):输入完整个数组之后,a[1]+a[2]+...+a[x]的值

逆序对

  1. 原数组:freq:{0,0,0,0,0,0} freq[i]表示遍历到当前位置,数字i出现的次数
  2. sum(x):遍历c:{5,4,2,6,3,1}过程中,freq[1]+freq[2]+...+freq[x]的值

离散化:

  1. freq(i)统计的是 数字i 出现的次数,i最大是\(2^{63} -1\),显然开不了这么大的数组

  2. 但是最多\(5*10^5\)个整数,将这些整数,相对大小不变,映射到\(1\)~\(5*10^5\)即可

  3. 强调:

    离散化去重——tmp数组变小,利于分配编号

    c数组大小不变(c与原始输入数组大小一致)

http://www.jsqmd.com/news/434969/

相关文章:

  • 信创架构深度重构:从兼容适配走向性能最优的全栈实践
  • 【开题答辩全过程】以 浩轩文化旅游网为例,包含答辩的问题和答案
  • 掌握敏捷中的使用者故事:如何撰寫高品質故事、建立測試案例,並善用 Visual Paradigm 的 AI 工具
  • 【2026最新】KeyShot下载安装全流程教程(附电脑版安装包+图文步骤) - sdfsafafa
  • 面向关键业务的信创架构:高可靠、高安全、高扩展设计指南
  • 探讨供应酒店一次性牙刷优质厂商,杭州邦亿客性价比怎么样? - myqiye
  • 探讨广州性价比高的防腐螺旋管厂家,防腐螺旋管品牌厂家推荐哪家? - 工业设备
  • 2026年3月高压储罐厂家推荐,精准检测与稳定性能深度解析 - 品牌鉴赏师
  • 多文档创建日期批量修改,高效省时方法分享
  • 分析防腐聚氨酯保温钢管选购要点,河北宝温管道性价比咋样 - 工业品网
  • 室内装修公司哪家性价比高,金螳螂家服务体验好不好 - mypinpai
  • 2026年3月DC-DC电源模块厂家推荐,精准检测与稳定性能深度解析 - 品牌鉴赏师
  • 华为OD机考双机位C卷 - 密码解密 (Java Python JS GO C++ C)
  • 防静电PC板选购指南:从入门到专业的5大核心标准 - 速递信息
  • 从单枪匹马到团队作战:手把手搭建一个能自我验证的多智能体软件开发工厂
  • 2026年3月盘管反应釜厂家推荐,精准检测与稳定性能深度解析 - 品牌鉴赏师
  • 2026年3月周界入侵干涉型光纤传感安防系统厂家推荐,聚焦企业综合实力竞争力 - 品牌鉴赏师
  • 百联 OK 卡回收避坑指南:安全变现,认准这几点就够了 - 团团收购物卡回收
  • C# 使用SharpCifs 对接SMB协议
  • 2026年食品级水性漆厂家推荐排行榜:自干/五金/塑胶/工业涂料/透明/手感/玻璃/烤漆/保温杯/泡沫板/树脂工艺品水性漆,环保高效应用广泛 - 品牌企业推荐师(官方)
  • 基于Qi协议的无线充电系统C语言实现
  • 说说杭州邦亿客酒店一次性用品,性价比咋样费用多少钱? - 工业品牌热点
  • 项目A文件存放架构(参考)
  • 文档修改日期怎么改?两步轻松调整
  • 百联 OK 卡闲置别放过期!过来人亲测靠谱回收方式,再也不踩坑 - 团团收购物卡回收
  • 2026年江苏发电机租赁/发电机出租/应急发电车出租选购指南:能源转型下的应急电力“避坑”指南与品牌实力测评 - 2026年企业推荐榜
  • 酒店一次性用品制造商价格实惠又靠谱的有哪些 - 工业推荐榜
  • 2026年3月齿轮齿条螺旋升降机厂家推荐,精准检测与稳定性能深度解析 - 品牌鉴赏师
  • 第一类斯特林数行
  • 2026年江苏发电机租赁/发电机出租/发电机回收/应急发电车出租全攻略:品牌推荐+采购指南,选对设备少走弯路 - 2026年企业推荐榜