LA4329乒乓比赛_树状数组
2016-01-11 21:05
302 查看
题目大意: 一条大街上住着n个乒乓球爱好者,经常组织比赛切磋技术。每个人都有一个能力值a[i]。每场比赛需要三个人:两名选手,一名裁判。他们有个奇怪的约定,裁判必须住在两名选手之间,而裁判的能力值也必须在两名选手之间。问一共能组织多少种比赛。 分析: 考虑第i个人,假设a1到ai-1中有ci个比ai小,那么就有(i-1)-ci个比ai大;同理,如果ai+1到an中有di个比ai小,那么就有(n-i)-di个比ai大。更具乘法原理和加法原理,i当裁判就有 ci * (n-i-di) + (i-1-ci)*di 种比赛。(感觉这种思路简直碉堡了) 然后问题就转化为了计算数组c和数组d。这样的话就很容易想到使用树状数组去计算前缀和。
比如输入一个数组,
PS:树状数组的运用主要目的是快速的累加和和修改值,所以这里使用了一个长度为100010的数组C,初始化为0,
如果我们输入 14 3 7 15 1 这样的话,第一次输入了14,所以C[14]+=1,变成1,然后从下面往上开始自增,在算cc[0]时候,传递过去num[i],然后使用加法模板来相加,这样结果就是14左边的小于14的值,dd也是一样的思路,注意dd的计算和cc的计算是相反的,从后往前加(可以想想为什么,注意树状数组相加时候只能从后往前累加!)。
代码如下
#include <iostream> #include <algorithm> using namespace std; #define MAXSIZE 100010 int num[MAXSIZE]; int C[MAXSIZE];//树状数组的段和 int cc[MAXSIZE];//cc[i]表示前面有多少元素比它小 int dd[MAXSIZE];//dd[i]表示后面有多少元素比它大 int n;//n代表输入元素的个数 #define LOWBITE(x) (x&(-x)) void add(int num,int increse) { while(num<MAXSIZE) { C[num]+=increse; num+=LOWBITE(num); } } int sum(int num) { int ret=0; while(num>0) { ret+=C[num]; num-=LOWBITE(num); } return ret; } int main() { int T; int i; int ans; cin>>T; while(T--) { cin>>n; ans=0; for( i=0;i<n;i++) { cin>>num[i]; } memset(C,0,sizeof(C)); memset(cc,0,sizeof(cc)); for(i=0;i<n;i++) { add(num[i],1); cc[i]=sum(num[i]-1); } memset(C,0,sizeof(C)); for(i=n-1;i>=0;i--) { add(num[i],1); dd[i]=sum(num[i]-1); } for(i=1;i<n;i++) { ans+=cc[i]*(n-i-1-dd[i])+(i-cc[i])*dd[i]; } cout<<ans<<endl; } return 0; }
相关文章推荐
- java web用户频繁非正常登出系统(session丢失)的原因分析及解决思路
- QTextEdit使用总结
- MySQL高级十一——慢查询
- SSL建立连接6
- 优化Android Studio/Gradle构建
- Delphi 的接口机制——接口操作的编译器实现过程(2)
- 二叉树基础存储结构——链表
- hdu 2094 产生冠军 寒假集训1 09
- SSL建立连接5
- iOS 关于隐藏键盘那些事儿
- Python 命令行解析工具 Argparse介绍(一)
- Delphi 的接口机制——接口操作的编译器实现过程(1)
- 重写ajax方法实现异步请求session过期时跳转登录页面
- DotSpatial 创建面状要素——含空洞
- oracle跨用户数据导入案例
- SSL建立连接4
- LeetCode__169. Majority Element
- 蓝桥杯 ALGO-92 前缀表达式
- 递归算法的时间复杂度终结篇
- xcode simulator不显示具体版本/解决xcode多个模拟器的办法