1009. Triple Inversions (35)
来源:互联网 发布:p2p理财返利平台源码 编辑:程序博客网 时间:2024/06/06 01:34
PAT上一道题目。题意是在一个1~n组成的n元数组A中,计算三元逆序的个数(满足i<j<k,Ai>Aj>Ak的(Ai,Aj,Ak))
的个数。
所有的三元逆序对,从中间数Aj考虑。对每一个数Ap,如果知道在p之前比Ap大的个数leftBigger以及在p 之后比Ap小的个数rightSmall。那么以Aj作为中间数的三元逆序对个数为leftBigger*rightSmall。对每一个p,计算以Ap为中间数的三元逆序,累加求和即可。计算leftBigger的方法可以采用树状数组。我们可以反过来看,已知Ap的位置p的情况下,计算leftBigger可以等价于计算leftSmall。leftBigger(Ap) = p-1-leftSmall(Ap)。先构建如下场景:
1.构建一个辅助数组a(1)~a(n).初始值均为0;
2.从左到右遍历A1~An.当遍历到Ap时,修改a(Ap) = 1;此时a(1)~a(Ap-1)值为1的个数即为在Ap的leftSmall(Ap),leftSmall(Ap) = sum(a(1)~a(Ap-1)).树状数组可以在lg(n)时间内计算出数组区间内元素之和。
代码如下:
#include<iostream>#include<vector>using namespace std;int main(){ int n; cin>>n; vector<int> nums(n+1); for(int i=1;i<=n;++i) { cin>>nums[i]; } vector<int> c(n+1,0); vector<int> leftSmall(n+1,0); for(int i=1;i<=n;++i) { int x = nums[i]-1; while(x>0){ leftSmall[nums[i]]+=c[x]; x-=x&(-x); } x = nums[i]; while(x<=n){ c[x]++; x+=x&(-x); } } long long ans = 0; for(int i=1;i<=n;++i) { long long leftBigger=0,rightSmall = 0; leftBigger = i-leftSmall[nums[i]]-1; rightSmall = nums[i] -1-leftSmall[nums[i]]; ans+=leftBigger*rightSmall; } cout<<ans<<endl; return 0;}
0 0
- 1009. Triple Inversions (35)
- 1009. Triple Inversions (35)
- 1009. Triple Inversions (35)
- 1009. Triple Inversions (35)解题报告
- pat-top 1009. Triple Inversions (35)
- PAT-TL 1009. Triple Inversions
- PAT (Top Level) Practise 1009 Triple Inversions (35)
- Inversions
- triple
- Triple
- hdu 5196 DZY Loves Inversions && BestCoder Round #35
- sgu180:Inversions
- Triple Buffering
- hdu517 Triple
- BZOJ3771: Triple
- BZOJ3771 Triple
- bzoj3771 Triple
- BZOJ3771: Triple
- JavaScript生成随机字符
- 如何上传图片到服务器(ios)
- 龙芯1B,龙芯1C系列VxWorks操作系统BSP调试完成
- 自定义通知的方法
- js中的KeyCode码
- 1009. Triple Inversions (35)
- 汇编语言将回车键的问题和集成开发的问题
- linux命令集锦之curl
- PAT乙级 打印沙漏(20)
- spring与Hibernate的整合(以及spring的声明式事务处理)
- 任意多边形面积
- 动态设置Layout的宽高值
- ansible高级用法
- 模块化程序设计函数与方法